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