The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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  */
25 RCSID("$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  */
48 static 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  */
59 typedef 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;
79  fr_pair_t *vp;
80  fr_value_box_t *in_head = fr_value_box_list_head(in);
81  fr_value_box_t *vb;
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);
110  fr_dcursor_append(out, vb);
111  return XLAT_ACTION_DONE;
112 }
113 
114 static void _trigger_last_fired_free(void *data)
115 {
116  talloc_free(data);
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  */
125 static 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  */
135 bool trigger_enabled(void)
136 {
137  return triggers_init;
138 }
139 
140 typedef 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.
147 } fr_trigger_t;
148 
149 static 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 
164 static 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 
202 static 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,
209  trigger->xlat, UNLANG_SUB_FRAME) < 0) RETURN_MODULE_FAIL;
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) {
257  cs = trigger_exec_main;
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);
409  if (unlang_subrequest_child_push_and_detach(request) < 0) {
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  */
454 void 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 
481 static int _mutex_free(pthread_mutex_t *mutex)
482 {
483  pthread_mutex_destroy(mutex);
484  return 0;
485 }
486 
487 /** Free trigger resources
488  *
489  */
490 static 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  */
512 static 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 
520  trigger_exec_main = cs;
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 
529  trigger_last_fired_t, node,
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:165
#define RCSID(id)
Definition: build.h:481
#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:110
#define UNUSED
Definition: build.h:313
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:3611
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_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition: cf_util.c:664
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
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
fr_dcursor_eval_t void const * uctx
Definition: dcursor.h:546
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:821
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
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
Definition: interpret.c:1764
void unlang_interpret_set(request_t *request, unlang_interpret_t *intp)
Set a specific interpreter for a request.
Definition: interpret.c:1745
#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
Definition: merged_model.c:31
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
long int ssize_t
Definition: merged_model.c:24
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
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
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
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
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
#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
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
The main red black tree structure.
Definition: rb.h:73
#define RETURN_MODULE_OK
Definition: rcode.h:57
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.
Definition: request_data.c:339
#define request_data_add(_request, _unique_ptr, _unique_int, _opaque, _free_on_replace, _free_on_parent, _persist)
Add opaque data to a request_t.
Definition: request_data.h:59
static char const * name
#define FR_SBUFF_IN(_start, _len_or_end)
RETURN_MODULE_FAIL
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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:274
bool required
Argument must be present, and non-empty.
Definition: xlat.h:146
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:406
#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:695
xlat_action_t
Definition: xlat.h:35
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition: xlat.h:42
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition: xlat.h:41
Definition for a single argument consumend by an xlat function.
Definition: xlat.h:145
#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