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: c8ce80e625ac235fe005e8bd2bc838cc01d30da7 $
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: c8ce80e625ac235fe005e8bd2bc838cc01d30da7 $")
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); /* @todo - 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, &(tmpl_rules_t) {
388 .attr = {
389 .dict_def = request->dict,
390 .list_def = request_attr_request,
391 .allow_unresolved = false,
392 },
393 }, true);
394 if (slen <= 0) {
395 char *spaces, *text;
396
397 fr_canonicalize_error(trigger, &spaces, &text, slen, trigger->command);
398
399 cf_log_err(cp, "Failed parsing trigger command");
400 cf_log_err(cp, "%s", text);
401 cf_log_perr(cp, "%s^", spaces);
402
403 talloc_free(request);
405 talloc_free(text);
406 return -1;
407 }
408
409 /*
410 * If we're not running it locally use the default
411 * interpreter for the thread.
412 */
413 if (intp) {
414 unlang_interpret_set(request, intp);
416 error:
417 PERROR("Running trigger failed");
418 talloc_free(request);
419 return -1;
420 }
421 }
422
423 if (xlat_finalize(trigger->xlat, intp ? unlang_interpret_event_list(request) : main_loop_event_list()) < 0) {
424 fr_strerror_const("Failed performing ephemeral instantiation for xlat");
425 talloc_free(request);
426 return -1;
427 }
428
430 NULL, 0, UNLANG_TOP_FRAME, trigger) < 0) goto error;
431
432 if (!intp) {
433 /*
434 * Wait for the exec to finish too,
435 * so where there are global events
436 * the request processes don't race
437 * with something like the server
438 * shutting down.
439 */
440 unlang_interpret_synchronous(NULL, request);
441 talloc_free(request);
442 }
443
444 /*
445 * Otherwise the worker cleans up the request request.
446 */
447 return 0;
448}
449
450/** Create trigger arguments to describe the server the pool connects to
451 *
452 * @note #trigger_exec_init must be called before calling this function,
453 * else it will return NULL.
454 *
455 * @param[in] ctx to allocate fr_pair_t s in.
456 * @param[out] list to append Pool-Server and Pool-Port pairs to
457 * @param[in] server we're connecting to.
458 * @param[in] port on that server.
459 */
460void trigger_args_afrom_server(TALLOC_CTX *ctx, fr_pair_list_t *list, char const *server, uint16_t port)
461{
462 fr_dict_attr_t const *server_da;
463 fr_dict_attr_t const *port_da;
464 fr_pair_t *vp;
465
466 server_da = fr_dict_attr_child_by_num(fr_dict_root(fr_dict_internal()), FR_CONNECTION_POOL_SERVER);
467 if (!server_da) {
468 ERROR("Incomplete dictionary: Missing definition for \"Connection-Pool-Server\"");
469 return;
470 }
471
472 port_da = fr_dict_attr_child_by_num(fr_dict_root(fr_dict_internal()), FR_CONNECTION_POOL_PORT);
473 if (!port_da) {
474 ERROR("Incomplete dictionary: Missing definition for \"Connection-Pool-Port\"");
475 return;
476 }
477
478 MEM(vp = fr_pair_afrom_da(ctx, server_da));
479 fr_pair_value_strdup(vp, server, false);
480 fr_pair_append(list, vp);
481
482 MEM(vp = fr_pair_afrom_da(ctx, port_da));
483 vp->vp_uint16 = port;
484 fr_pair_append(list, vp);
485}
486
487static int _mutex_free(pthread_mutex_t *mutex)
488{
489 pthread_mutex_destroy(mutex);
490 return 0;
491}
492
493/** Free trigger resources
494 *
495 */
496static int _trigger_exec_free(UNUSED void *uctx)
497{
498 TALLOC_FREE(trigger_last_fired_tree);
499 TALLOC_FREE(trigger_mutex);
500
501 return 0;
502}
503
504/** Set the global trigger section trigger_exec will search in, and register xlats
505 *
506 * This function exists because triggers are used by the connection pool, which
507 * is used in the server library which may not have the mainconfig available.
508 * Additionally, utilities may want to set their own root config sections.
509 *
510 * We don't register the trigger xlat here, as we may inadvertently initialise
511 * the xlat code, which is annoying when this is called from a utility.
512 *
513 * @param[in] cs_arg to use as global trigger section.
514 * @return
515 * - 0 on success.
516 * - -1 on failure.
517 */
518static int _trigger_exec_init(void *cs_arg)
519{
520 CONF_SECTION *cs = talloc_get_type_abort(cs_arg, CONF_SECTION);
521 if (!cs) {
522 ERROR("%s - Pointer to main_config was NULL", __FUNCTION__);
523 return -1;
524 }
525
527 trigger_exec_subcs = cf_section_find(cs, "trigger", NULL);
528
529 if (!trigger_exec_subcs) {
530 WARN("trigger { ... } subsection not found, triggers will be disabled");
531 return 0;
532 }
533
537
539 pthread_mutex_init(trigger_mutex, 0);
540 talloc_set_destructor(trigger_mutex, _mutex_free);
541 triggers_init = true;
542
543 return 0;
544}
545
547{
548 int ret;
549
550 fr_atexit_global_once_ret(&ret, _trigger_exec_init, _trigger_exec_free, UNCONST(CONF_SECTION *, cs));
551
552 return ret;
553}
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:67
CONF_ITEM * cf_reference_item(CONF_SECTION const *parent_cs, CONF_SECTION const *outer_cs, char const *ptr)
Definition cf_file.c:3715
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:3270
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2407
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:4617
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:3335
static fr_slen_t in
Definition dict.h:831
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: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:1760
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
Definition interpret.c:1779
#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: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_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)
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:337
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:518
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:460
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:487
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:546
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:496
#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:287
bool required
Argument must be present, and non-empty.
Definition xlat.h:148
static fr_slen_t head
Definition xlat.h:418
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: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:3759
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