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: 7270645e97d8b30d3689aa52354c1f9b75edf1a9 $
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: 7270645e97d8b30d3689aa52354c1f9b75edf1a9 $")
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#include <freeradius-devel/unlang/tmpl.h>
38
39
40#include <sys/wait.h>
41
42/** Whether triggers are enabled globally
43 *
44 */
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 (!trigger_cs) {
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 (trigger_cs != NULL);
133}
134
135typedef struct {
136 fr_value_box_list_t args; //!< Arguments to pass to the trigger exec.
137 fr_value_box_list_t out; //!< result of the xlap (which we ignore)
138 unlang_result_t result; //!< the result of expansion
141
142/** Execute a trigger - call an executable to process an event
143 *
144 * A trigger ties a state change (e.g. connection up) in a module to an action
145 * (e.g. send an SNMP trap) defined in raqddb/triggers.conf or in the trigger
146 * section of a module, and can be created with one call to trigger_exec().
147 *
148 * The trigger_exec function expands the configuration item, and runs the given
149 * function (exec, sql insert, etc.) asynchronously, allowing the server to
150 * keep processing packets while the action is being taken.
151 *
152 * The name of each trigger is based on the module or portion of the server
153 * which runs the trigger, and is usually taken from the state when the module
154 * has a state change.
155 *
156 * Triggers are separate from logs, because log messages are generally
157 * informational, are not time sensitive, and usually require log files to be
158 * parsed and filtered in order to find relevant information.
159 *
160 * In contrast, triggers are something specific which the administrator needs
161 * to be notified about immediately and can't wait to post-process a log file.
162 *
163 * @note Calls to this function will be ignored if #trigger_exec_init has not been called.
164 *
165 * @param[in] intp Interpreter to run the trigger with. If this is NULL the
166 * trigger will be executed synchronously.
167 * @param[in] cs to search for triggers in.
168 * If cs is not NULL, the portion after the last '.' in name is used for the trigger.
169 * If cs is NULL, the entire name is used to find the trigger in the global trigger
170 * section.
171 * @param[in] name the path relative to the global trigger section ending in the trigger name
172 * e.g. module.ldap.pool.start.
173 * @param[in] rate_limit whether to rate limit triggers.
174 * @param[in] args to make available via the @verbatim %trigger(<arg>) @endverbatim xlat.
175 * @return
176 * - 0 on success.
177 * - -1 on failure.
178 */
180 CONF_SECTION const *cs, char const *name, bool rate_limit, fr_pair_list_t *args)
181{
182 CONF_ITEM *ci;
183 CONF_PAIR *cp;
184
185 char const *attr;
186 char const *value;
187
188 request_t *request;
189 fr_trigger_t *trigger;
190 ssize_t slen;
191
193 xlat_exp_head_t *xlat;
194 tmpl_rules_t t_rules;
195 fr_token_t quote;
196
197 /*
198 * noop if trigger_exec_init was never called, or if
199 * we're just checking the configuration.
200 */
201 if (!trigger_cs || check_config) return 0;
202
203 /*
204 * A module can have a local "trigger" section. In which
205 * case that is used in preference to the global one.
206 *
207 * @todo - we should really allow triggers via @trigger,
208 * so that all of the triggers are in one location. And
209 * then we can have different triggers for different
210 * module instances.
211 */
212 if (cs) {
213 CONF_SECTION const *subcs;
214
215 subcs = cf_section_find(cs, "trigger", NULL);
216 if (!subcs) goto use_global;
217
218 /*
219 * If a local trigger{...} section exists, then
220 * use the local part of the name, rather than
221 * the full path.
222 */
223 attr = strrchr(name, '.');
224 if (attr) {
225 attr++;
226 } else {
227 attr = name;
228 }
229 } else {
230 use_global:
231 cs = trigger_cs;
232 attr = name;
233 }
234
235 /*
236 * Find the trigger. Note that we do NOT allow searching
237 * from the root of the tree. Triggers MUST be in a
238 * trigger{...} section.
239 */
240 ci = cf_reference_item(cs, cs, attr);
241 if (!ci) {
242 if (cs != trigger_cs) goto use_global; /* not found locally, try to find globally */
243
244 DEBUG3("Failed finding trigger '%s'", attr);
245 return -1;
246 }
247
248 if (!cf_item_is_pair(ci)) {
249 ERROR("Trigger is not a configuration variable: %s", attr);
250 return -1;
251 }
252
253 cp = cf_item_to_pair(ci);
254 if (!cp) return -1;
255
256 value = cf_pair_value(cp);
257 if (!value) {
258 DEBUG3("Trigger has no value: %s", name);
259 return -1;
260 }
261
262 /*
263 * Perform periodic rate_limiting.
264 */
265 if (rate_limit) {
266 trigger_last_fired_t find, *found;
267 fr_time_t now = fr_time();
268
269 find.ci = ci;
270
271 pthread_mutex_lock(trigger_mutex);
272
273 found = fr_rb_find(trigger_last_fired_tree, &find);
274 if (!found) {
275 MEM(found = talloc(NULL, trigger_last_fired_t));
276 found->ci = ci;
277 /*
278 * Initialise last_fired to 2 seconds ago so
279 * the trigger fires on the first occurrence
280 */
281 found->last_fired = fr_time_wrap(NSEC * -2);
282
284 }
285
286 pthread_mutex_unlock(trigger_mutex);
287
288 /*
289 * Send the rate_limited traps at most once per second.
290 *
291 * @todo - make this configurable for longer periods of time.
292 */
293 if (fr_time_to_sec(found->last_fired) == fr_time_to_sec(now)) return -1;
294 found->last_fired = now;
295 }
296
297 /*
298 * Allocate a request to run asynchronously in the interpreter.
299 */
300 request = request_local_alloc_internal(NULL, (&(request_init_args_t){ .detachable = true }));
301
302 /*
303 * Add the args to the request data, so they can be picked up by the
304 * trigger_xlat function.
305 */
306 if (args) {
307 fr_pair_list_t *local_args;
308
309 MEM(local_args = talloc_zero(request, fr_pair_list_t));
310 fr_pair_list_init(local_args);
311 if (fr_pair_list_copy(local_args, local_args, args) < 0) {
312 PERROR("Failed copying trigger arguments");
313 args_error:
314 talloc_free(request);
315 return -1;
316 }
317
318 if (request_data_add(request, &trigger_cs, REQUEST_INDEX_TRIGGER_ARGS, local_args,
319 false, false, false) < 0) goto args_error;
320 }
321
323 UNCONST(char *, name), false, false, false) < 0) {
324 talloc_free(request);
325 return -1;
326 }
327
328 MEM(trigger = talloc_zero(request, fr_trigger_t));
329 fr_value_box_list_init(&trigger->args);
330 fr_value_box_list_init(&trigger->out);
331
333 if (!el) el = main_loop_event_list();
334
335 t_rules = (tmpl_rules_t) {
336 .attr = {
337 .dict_def = request->local_dict, /* we can use local attributes */
338 .list_def = request_attr_request,
339 },
340 .xlat = {
341 .runtime_el = el,
342 },
343 .at_runtime = true,
344 };
345
346 quote = cf_pair_value_quote(cp);
347
348 /*
349 * Parse the xlat as appropriate.
350 */
351 if (quote != T_BACK_QUOTED_STRING) {
352 slen = xlat_tokenize(trigger, &xlat, &FR_SBUFF_IN(value, talloc_array_length(value) - 1), NULL, &t_rules);
353 } else {
354 slen = xlat_tokenize_argv(trigger, &xlat, &FR_SBUFF_IN(value, talloc_array_length(value) - 1), NULL, NULL, &t_rules, true);
355 }
356 if (slen <= 0) {
357 char *spaces, *text;
358
359 fr_canonicalize_error(trigger, &spaces, &text, slen, value);
360
361 cf_log_err(cp, "Failed parsing trigger command");
362 cf_log_err(cp, "%s", text);
363 cf_log_perr(cp, "%s^", spaces);
364
365 talloc_free(request);
367 talloc_free(text);
368 return -1;
369 }
370
371 fr_assert(xlat != NULL);
372
373 if (quote != T_BACK_QUOTED_STRING) {
374 if (unlang_xlat_push(trigger, &trigger->result, &trigger->out, request, xlat, true) < 0) {
375 fail_expand:
376 DEBUG("Failed expanding trigger - %s", fr_strerror());
377 talloc_free(request);
378 return -1;
379 }
380 } else {
381 tmpl_t *vpt;
382
383 /*
384 * We need back-ticks, because it's just so much
385 * easier than anything else.
386 *
387 * @todo - define %exec.string() function, which
388 * splits the string, and THEN expands it. That
389 * would be much simpler than this stuff.
390 */
391 MEM(vpt = tmpl_alloc(trigger, TMPL_TYPE_EXEC, quote, value, talloc_array_length(value)));
392 tmpl_set_xlat(vpt, xlat);
393
394 if (unlang_tmpl_push(trigger, &trigger->out, request, vpt,
396 .type = UNLANG_TMPL_ARGS_TYPE_EXEC,
397 .exec = {
398 .status_out = &trigger->exec_status,
399 .timeout = fr_time_delta_from_sec(1),
400 },
401 }) < 0) {
402 goto fail_expand;
403 }
404 }
405
406 /*
407 * An interpreter was passed in, we can run the expansion
408 * asynchronously in that interpreter. And then the
409 * worker cleans up the detached request.
410 */
411 if (intp) {
412 unlang_interpret_set(request, intp);
413
414 /*
415 * Don't allow the expansion to run for a long time.
416 *
417 * @todo - make the timeout configurable.
418 */
420 DEBUG("Failed setting timeout on trigger %s", value);
421 talloc_free(request);
422 return -1;
423 }
424
426 PERROR("Running trigger failed");
427 talloc_free(request);
428 return -1;
429 }
430 } else {
431 /*
432 * No interpreter, we MUST be running from the
433 * main loop. We then run the expansion
434 * synchronously. This allows the expansion /
435 * notification to finish before the server shuts
436 * down.
437 *
438 * If the expansion was async, then it may be
439 * possible for the server to exit before the
440 * expansion finishes. Arguably the worker
441 * thread should ensure that the server doesn't
442 * exit until all requests have acknowledged that
443 * they've exited.
444 *
445 * But those exits may be advisory. i.e. "please
446 * finish the request". This one here is
447 * mandatary to finish before the server exits.
448 */
449 unlang_interpret_synchronous(NULL, request);
450 talloc_free(request);
451 }
452
453 return 0;
454}
455
456/** Create trigger arguments to describe the server the pool connects to
457 *
458 * @note #trigger_exec_init must be called before calling this function,
459 * else it will return NULL.
460 *
461 * @param[in] ctx to allocate fr_pair_t s in.
462 * @param[out] list to append Pool-Server and Pool-Port pairs to
463 * @param[in] server we're connecting to.
464 * @param[in] port on that server.
465 */
466void trigger_args_afrom_server(TALLOC_CTX *ctx, fr_pair_list_t *list, char const *server, uint16_t port)
467{
468 fr_dict_attr_t const *server_da;
469 fr_dict_attr_t const *port_da;
470 fr_pair_t *vp;
471
472 server_da = fr_dict_attr_child_by_num(fr_dict_root(fr_dict_internal()), FR_CONNECTION_POOL_SERVER);
473 if (!server_da) {
474 ERROR("Incomplete dictionary: Missing definition for \"Connection-Pool-Server\"");
475 return;
476 }
477
478 port_da = fr_dict_attr_child_by_num(fr_dict_root(fr_dict_internal()), FR_CONNECTION_POOL_PORT);
479 if (!port_da) {
480 ERROR("Incomplete dictionary: Missing definition for \"Connection-Pool-Port\"");
481 return;
482 }
483
484 MEM(vp = fr_pair_afrom_da(ctx, server_da));
485 fr_pair_value_strdup(vp, server, false);
486 fr_pair_append(list, vp);
487
488 MEM(vp = fr_pair_afrom_da(ctx, port_da));
489 vp->vp_uint16 = port;
490 fr_pair_append(list, vp);
491}
492
493static int _mutex_free(pthread_mutex_t *mutex)
494{
495 pthread_mutex_destroy(mutex);
496 return 0;
497}
498
499/** Free trigger resources
500 *
501 */
502static int _trigger_exec_free(UNUSED void *uctx)
503{
504 TALLOC_FREE(trigger_last_fired_tree);
505 TALLOC_FREE(trigger_mutex);
506
507 return 0;
508}
509
510/** Set the global trigger section trigger_exec will search in, and register xlats
511 *
512 * This function exists because triggers are used by the connection pool, which
513 * is used in the server library which may not have the mainconfig available.
514 * Additionally, utilities may want to set their own root config sections.
515 *
516 * We don't register the trigger xlat here, as we may inadvertently initialise
517 * the xlat code, which is annoying when this is called from a utility.
518 *
519 * @param[in] cs_arg to use as global trigger section.
520 * @return
521 * - 0 on success.
522 * - -1 on failure.
523 */
524static int _trigger_exec_init(void *cs_arg)
525{
526 CONF_SECTION *cs = talloc_get_type_abort(cs_arg, CONF_SECTION);
527 if (!cs) {
528 ERROR("%s - Pointer to main_config was NULL", __FUNCTION__);
529 return -1;
530 }
531
532 trigger_cs = cf_section_find(cs, "trigger", NULL);
533 if (!trigger_cs) {
534 WARN("trigger { ... } subsection not found, triggers will be disabled");
535 return 0;
536 }
537
541
543 pthread_mutex_init(trigger_mutex, 0);
544 talloc_set_destructor(trigger_mutex, _mutex_free);
545
546 return 0;
547}
548
550{
551 int ret;
552
553 fr_atexit_global_once_ret(&ret, _trigger_exec_init, _trigger_exec_free, UNCONST(CONF_SECTION *, cs));
554
555 return ret;
556}
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:63
CONF_ITEM * cf_reference_item(CONF_SECTION const *parent_cs, CONF_SECTION const *outer_cs, char const *ptr)
Definition cf_file.c:3550
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
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
Definition cf_util.c:1637
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:408
#define MEM(x)
Definition debug.h:36
static char const * spaces
Definition dependency.c:370
#define ERROR(fmt,...)
Definition dhcpclient.c:41
#define DEBUG(fmt,...)
Definition dhcpclient.c:39
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:3266
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2403
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:4654
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:3331
static fr_slen_t in
Definition dict.h:841
Test enumeration values.
Definition dict_test.h:92
int unlang_interpret_set_timeout(request_t *request, fr_time_delta_t timeout)
Set a timeout for a request.
Definition interpret.c:1504
void unlang_interpret_set(request_t *request, unlang_interpret_t *intp)
Set a specific interpreter for a request.
Definition interpret.c:1998
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
Definition interpret.c:2017
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
talloc_free(reap)
Stores all information relating to an event list.
Definition event.c:377
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:2320
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
Definition pair.c:2636
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:697
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:1342
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:287
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
#define fr_assert(_expr)
Definition rad_assert.h:38
#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
fr_dict_attr_t const * request_attr_request
Definition request.c:43
#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)
void tmpl_set_xlat(tmpl_t *vpt, xlat_exp_head_t *xlat)
Change the default dictionary in the tmpl's resolution rules.
tmpl_t * tmpl_alloc(TALLOC_CTX *ctx, tmpl_type_t type, fr_token_t quote, char const *name, ssize_t len)
Create a new heap allocated tmpl_t.
@ TMPL_TYPE_EXEC
Callout to an external script or program.
Definition tmpl.h:150
static fr_slen_t vpt
Definition tmpl.h:1269
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:335
struct tmpl_rules_s tmpl_rules_t
Definition tmpl.h:233
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
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition tmpl.h:273
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
int unlang_subrequest_child_push_and_detach(request_t *request)
Add a child request to the runnable queue.
Definition subrequest.c:501
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
"server local" time.
Definition time.h:69
int unlang_tmpl_push(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, tmpl_t const *tmpl, unlang_tmpl_args_t *args)
Push a tmpl onto the stack for evaluation.
Definition tmpl.c:254
enum fr_token fr_token_t
@ T_BACK_QUOTED_STRING
Definition token.h:123
static int _trigger_exec_init(void *cs_arg)
Set the global trigger section trigger_exec will search in, and register xlats.
Definition trigger.c:524
int exec_status
Definition trigger.c:139
fr_value_box_list_t args
Arguments to pass to the trigger exec.
Definition trigger.c:136
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:466
xlat_arg_parser_t const trigger_xlat_args[]
Definition trigger.c:61
static int _mutex_free(pthread_mutex_t *mutex)
Definition trigger.c:493
int trigger_exec_init(CONF_SECTION const *cs)
Definition trigger.c:549
fr_rb_node_t node
Entry in the trigger last fired tree.
Definition trigger.c:56
fr_value_box_list_t out
result of the xlap (which we ignore)
Definition trigger.c:137
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:502
#define REQUEST_INDEX_TRIGGER_NAME
Definition trigger.c:49
static fr_rb_tree_t * trigger_last_fired_tree
Definition trigger.c:46
#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
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:179
unlang_result_t result
the result of expansion
Definition trigger.c:138
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
static CONF_SECTION const * trigger_cs
Whether triggers are enabled globally.
Definition trigger.c:45
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
Describes a rate limiting entry for a trigger.
Definition trigger.c:55
static fr_event_list_t * el
Arguments for evaluating different types of tmpls.
Definition tmpl.h:48
int unlang_xlat_push(TALLOC_CTX *ctx, unlang_result_t *p_result, 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
fr_slen_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
Tokenize an xlat expansion.
static fr_slen_t head
Definition xlat.h:420
uint8_t required
Argument must be present, and non-empty.
Definition xlat.h:146
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:170
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
fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, xlat_arg_parser_t const *xlat_args, 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.
Definition for a single argument consumend by an xlat function.
Definition xlat.h:145
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:553
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:3962
static fr_slen_t data
Definition value.h:1288
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition value.h:651
static size_t char ** out
Definition value.h:1020
An xlat calling ctx.
Definition xlat_ctx.h:49