The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
module.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: 929ecbc1efe3216dcb2d65570e0c360b5e752739 $
19  *
20  * @file unlang/module.c
21  * @brief Defines functions for calling modules asynchronously
22  *
23  * @copyright 2018 The FreeRADIUS server project
24  * @copyright 2018 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
25  */
26 
27 RCSID("$Id: 929ecbc1efe3216dcb2d65570e0c360b5e752739 $")
28 
29 #include <freeradius-devel/server/modpriv.h>
30 #include <freeradius-devel/server/request_data.h>
31 #include <freeradius-devel/server/rcode.h>
32 #include <freeradius-devel/unlang/call_env.h>
33 
34 #include "module_priv.h"
35 #include "subrequest_priv.h"
36 
37 #include "tmpl.h"
38 
39 /** Wrap an #fr_event_timer_t providing data needed for unlang events
40  *
41  */
42 typedef struct {
43  request_t *request; //!< Request this event pertains to.
44  int fd; //!< File descriptor to wait on.
45  unlang_module_timeout_t timeout; //!< Function to call on timeout.
46  unlang_module_fd_event_t fd_read; //!< Function to call when FD is readable.
47  unlang_module_fd_event_t fd_write; //!< Function to call when FD is writable.
48  unlang_module_fd_event_t fd_error; //!< Function to call when FD has errored.
49  dl_module_inst_t *dl_inst; //!< Module instance to pass to callbacks.
50  ///< Use dl_inst->data to get instance data.
51  void *thread; //!< Thread specific module instance.
52  void *env_data; //!< Per call environment data.
53  void const *rctx; //!< rctx data to pass to callbacks.
54  fr_event_timer_t const *ev; //!< Event in this worker's event heap.
56 
58 
59 /** Call the callback registered for a read I/O event
60  *
61  * @param[in] el containing the event (not passed to the callback).
62  * @param[in] fd the I/O event occurred on.
63  * @param[in] flags from kevent.
64  * @param[in] ctx unlang_module_event_t structure holding callbacks.
65  */
66 static void unlang_event_fd_read_handler(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *ctx)
67 {
68  unlang_module_event_t *ev = talloc_get_type_abort(ctx, unlang_module_event_t);
69 
70  fr_assert(ev->fd == fd);
71 
72  ev->fd_read(MODULE_CTX(ev->dl_inst, ev->thread, ev->env_data, UNCONST(void *, ev->rctx)), ev->request, fd);
73 }
74 
75 /** Frees an unlang event, removing it from the request's event loop
76  *
77  * @param[in] ev The event to free.
78  *
79  * @return 0
80  */
82 {
83  if (ev->request) (void) request_data_get(ev->request, ev->rctx, UNLANG_TYPE_MODULE);
84 
85  if (ev->ev) {
86  (void) fr_event_timer_delete(&(ev->ev));
87  return 0;
88  }
89 
90  if (ev->fd >= 0) {
91  if (!ev->request) return 0;
93  }
94 
95  return 0;
96 }
97 
98 /** Call the callback registered for a timeout event
99  *
100  * @param[in] el the event timer was inserted into.
101  * @param[in] now The current time, as held by the event_list.
102  * @param[in] ctx unlang_module_event_t structure holding callbacks.
103  *
104  */
106 {
107  unlang_module_event_t *ev = talloc_get_type_abort(ctx, unlang_module_event_t);
108 
109  ev->timeout(MODULE_CTX(ev->dl_inst, ev->thread, ev->env_data, UNCONST(void *, ev->rctx)), ev->request, now);
110  talloc_free(ev);
111 }
112 
113 /** Set a timeout for the request.
114  *
115  * Used when a module needs wait for an event. Typically the callback is set, and then the
116  * module returns unlang_module_yield().
117  *
118  * @note The callback is automatically removed on unlang_interpret_mark_runnable().
119  *
120  * param[in] request the current request.
121  * param[in] callback to call.
122  * param[in] rctx to pass to the callback.
123  * param[in] timeout when to call the timeout (i.e. now + timeout).
124  * @return
125  * - 0 on success.
126  * - <0 on error.
127  */
129  void const *rctx, fr_time_t when)
130 {
131  unlang_stack_t *stack = request->stack;
132  unlang_stack_frame_t *frame = &stack->frame[stack->depth];
134  unlang_module_t *mc;
135  unlang_frame_state_module_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_module_t);
136 
137  fr_assert(stack->depth > 0);
140 
141  ev = talloc(request, unlang_module_event_t);
142  if (!ev) return -1;
143 
144  *ev = (unlang_module_event_t){
145  .request = request,
146  .fd = -1,
147  .timeout = callback,
148  .dl_inst = mc->instance->dl_inst,
149  .thread = state->thread,
150  .env_data = state->env_data,
151  .rctx = rctx
152  };
153 
154  if (fr_event_timer_at(request, unlang_interpret_event_list(request), &ev->ev,
155  when, unlang_module_event_timeout_handler, ev) < 0) {
156  RPEDEBUG("Failed inserting event");
157  talloc_free(ev);
158  return -1;
159  }
160 
161  (void) request_data_talloc_add(request, rctx, UNLANG_TYPE_MODULE, unlang_module_event_t, ev, true, false, false);
162 
163  talloc_set_destructor(ev, _unlang_event_free);
164 
165  return 0;
166 }
167 
168 /** Delete a previously set timeout callback
169  *
170  * @param[in] request The current request.
171  * @param[in] ctx a local context for the callback.
172  * @return
173  * - -1 on error.
174  * - 0 on success.
175  */
176 int unlang_module_timeout_delete(request_t *request, void const *ctx)
177 {
179 
180  ev = request_data_get(request, ctx, UNLANG_TYPE_MODULE);
181  if (!ev) return -1;
182  talloc_free(ev);
183 
184  return 0;
185 }
186 
187 /** Call the callback registered for a write I/O event
188  *
189  * @param[in] el containing the event (not passed to the callback).
190  * @param[in] fd the I/O event occurred on.
191  * @param[in] flags from kevent.
192  * @param[in] ctx unlang_module_event_t structure holding callbacks.
193  */
194 static void unlang_event_fd_write_handler(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *ctx)
195 {
196  unlang_module_event_t *ev = talloc_get_type_abort(ctx, unlang_module_event_t);
197  fr_assert(ev->fd == fd);
198 
199  ev->fd_write(MODULE_CTX(ev->dl_inst, ev->thread, ev->env_data, UNCONST(void *, ev->rctx)), ev->request, fd);
200 }
201 
202 /** Call the callback registered for an I/O error event
203  *
204  * @param[in] el containing the event (not passed to the callback).
205  * @param[in] fd the I/O event occurred on.
206  * @param[in] flags from kevent.
207  * @param[in] fd_errno from kevent.
208  * @param[in] ctx unlang_module_event_t structure holding callbacks.
209  */
211  UNUSED int flags, UNUSED int fd_errno, void *ctx)
212 {
213  unlang_module_event_t *ev = talloc_get_type_abort(ctx, unlang_module_event_t);
214 
215  fr_assert(ev->fd == fd);
216 
217  ev->fd_error(MODULE_CTX(ev->dl_inst, ev->thread, ev->env_data, UNCONST(void *, ev->rctx)), ev->request, fd);
218 }
219 
220 
221 /** Set a callback for the request.
222  *
223  * Used when a module needs to read from an FD. Typically the callback is set, and then the
224  * module returns unlang_module_yield().
225  *
226  * @note The callback is automatically removed on unlang_interpret_mark_runnable().
227  *
228  * @param[in] request The current request.
229  * @param[in] read callback. Used for receiving and demuxing/decoding data.
230  * @param[in] write callback. Used for writing and encoding data.
231  * Where a 3rd party library is used, this should be the function
232  * issuing queries, and writing data to the socket. This should
233  * not be done in the module itself.
234  * This allows write operations to be retried in some instances,
235  * and means if the write buffer is full, the request is kept in
236  * a suspended state.
237  * @param[in] error callback. If the fd enters an error state. Should cleanup any
238  * handles wrapping the file descriptor, and any outstanding requests.
239  * @param[in] rctx for the callback.
240  * @param[in] fd to watch.
241  * @return
242  * - 0 on success.
243  * - <0 on error.
244  */
249  void const *rctx, int fd)
250 {
251  unlang_stack_t *stack = request->stack;
252  unlang_stack_frame_t *frame = &stack->frame[stack->depth];
254  unlang_module_t *mc;
255  unlang_frame_state_module_t *state = talloc_get_type_abort(frame->state,
257 
258  fr_assert(stack->depth > 0);
259 
262 
263  ev = talloc_zero(request, unlang_module_event_t);
264  if (!ev) return -1;
265 
266  ev->request = request;
267  ev->fd = fd;
268  ev->fd_read = read;
269  ev->fd_write = write;
270  ev->fd_error = error;
271  ev->dl_inst = mc->instance->dl_inst;
272  ev->thread = state->thread;
273  ev->env_data = state->env_data;
274  ev->rctx = rctx;
275 
276  /*
277  * Register for events on the file descriptor
278  */
279  if (fr_event_fd_insert(request, NULL, unlang_interpret_event_list(request), fd,
283  ev) < 0) {
284  talloc_free(ev);
285  return -1;
286  }
287 
288  (void) request_data_talloc_add(request, rctx, fd, unlang_module_event_t, ev, true, false, false);
289  talloc_set_destructor(ev, _unlang_event_free);
290 
291  return 0;
292 }
293 
294 /** Delete a previously set file descriptor callback
295  *
296  * param[in] request the request
297  * param[in] fd the file descriptor
298  * @return
299  * - 0 on success.
300  * - <0 on error.
301  */
302 int unlang_module_fd_delete(request_t *request, void const *ctx, int fd)
303 {
305 
306  ev = request_data_get(request, ctx, fd);
307  if (!ev) return -1;
308 
309  talloc_free(ev);
310  return 0;
311 }
312 
313 /** Push a module or submodule onto the stack for evaluation
314  *
315  * @param[out] p_result Where to write the result of calling the module.
316  * @param[in] request The current request.
317  * @param[in] module_instance Instance of the module to call.
318  * @param[in] method to call.
319  * @param[in] top_frame Set to UNLANG_TOP_FRAME if the interpreter should return.
320  * Set to UNLANG_SUB_FRAME if the interprer should continue.
321  * @return
322  * - 0 on success.
323  * - -1 on failure.
324  */
325 int unlang_module_push(rlm_rcode_t *p_result, request_t *request,
326  module_instance_t *module_instance, module_method_t method, bool top_frame)
327 {
328  unlang_stack_t *stack = request->stack;
329  unlang_stack_frame_t *frame;
331  unlang_module_t *mc;
332 
333  /*
334  * We need to have a unlang_module_t to push on the
335  * stack. The only sane way to do it is to attach it to
336  * the frame state.
337  */
338  MEM(mc = talloc(stack, unlang_module_t)); /* Still gets allocated from the stack pool */
339  *mc = (unlang_module_t){
340  .self = {
342  .name = module_instance->name,
343  .debug_name = module_instance->name,
344  .actions = {
345  .actions = {
346  [RLM_MODULE_REJECT] = 0,
347  [RLM_MODULE_FAIL] = MOD_ACTION_RETURN, /* Exit out of nested levels */
348  [RLM_MODULE_OK] = 0,
349  [RLM_MODULE_HANDLED] = 0,
350  [RLM_MODULE_INVALID] = 0,
351  [RLM_MODULE_DISALLOW] = 0,
352  [RLM_MODULE_NOTFOUND] = 0,
353  [RLM_MODULE_NOOP] = 0,
354  [RLM_MODULE_UPDATED] = 0
355  },
356  .retry = RETRY_INIT,
357  },
358  },
359  .instance = module_instance,
360  .method = method
361  };
362 
363  /*
364  * Push a new module frame onto the stack
365  */
367  RLM_MODULE_NOT_SET, UNLANG_NEXT_STOP, top_frame) < 0) {
368  return -1;
369  }
370 
371  frame = &stack->frame[stack->depth];
372  state = frame->state;
373  *state = (unlang_frame_state_module_t){
374  .p_result = p_result,
375  .thread = module_thread(module_instance)
376  };
377 
378  /*
379  * Bind the temporary unlang_module_t to the frame state.
380  *
381  * There aren't _that_ many children in the stack context.
382  * so we should be ok.
383  *
384  * Hopefully in future versions of talloc the O(n) problem
385  * will be fixed for stealing.
386  */
387  talloc_steal(state, mc);
388 
389  return 0;
390 }
391 
392 /** Change the resume function of a module.
393  *
394  * @param[in] request The current request.
395  * @param[in] resume function to call when the XLAT expansion is complete.
396  * @return
397  * - <0 on error
398  * - 0 on success
399  */
401 {
402  unlang_stack_t *stack = request->stack;
403  unlang_stack_frame_t *frame = &stack->frame[stack->depth];
405 
406  /*
407  * Can't resume if it isn't yielded.
408  */
409  if (!is_yielded(frame)) return -1;
410 
411  /*
412  * It must be yielded in a module.
413  */
414  if (frame->instruction->type != UNLANG_TYPE_MODULE) return -1;
415 
416  state = talloc_get_type_abort(frame->state, unlang_frame_state_module_t);
417  state->resume = resume;
418 
419  return 0;
420 }
421 
422 /** Push a pre-compiled xlat and resumption state onto the stack for evaluation
423  *
424  * In order to use the async unlang processor the calling module needs to establish
425  * a resumption point, as the call to an xlat function may require yielding control
426  * back to the interpreter.
427  *
428  * To simplify the calling conventions, this function is provided to first push a
429  * resumption stack frame for the module, and then push an xlat stack frame.
430  *
431  * After pushing those frames the function updates the stack pointer to jump over
432  * the resumption frame and execute the xlat interpreter.
433  *
434  * When the xlat interpreter finishes, and pops the xlat frame, the unlang interpreter
435  * will then call the module resumption frame, allowing the module to continue execution.
436  *
437  * @param[in] ctx To allocate talloc value boxes and values in.
438  * @param[out] p_success Whether xlat evaluation was successful.
439  * @param[out] out Where to write the result of the expansion.
440  * @param[in] request The current request.
441  * @param[in] exp XLAT expansion to evaluate.
442  * @param[in] resume function to call when the XLAT expansion is complete.
443  * @param[in] signal function to call if a signal is received.
444  * @param[in] sigmask Signals to block.
445  * @param[in] rctx to pass to the resume() and signal() callbacks.
446  * @return
447  * - UNLANG_ACTION_PUSHED_CHILD
448  */
449 unlang_action_t unlang_module_yield_to_xlat(TALLOC_CTX *ctx, bool *p_success, fr_value_box_list_t *out,
450  request_t *request, xlat_exp_head_t const *exp,
451  module_method_t resume,
452  unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
453 {
454  /*
455  * Push the resumption point BEFORE pushing the xlat onto
456  * the parents stack.
457  */
458  (void) unlang_module_yield(request, resume, signal, sigmask, rctx);
459 
460  /*
461  * Push the xlat function
462  */
463  if (unlang_xlat_push(ctx, p_success, out, request, exp, false) < 0) return UNLANG_ACTION_STOP_PROCESSING;
464 
466 }
467 
468 /** Push a pre-compiled tmpl and resumption state onto the stack for evaluation
469  *
470  * In order to use the async unlang processor the calling module needs to establish
471  * a resumption point, as the call to an xlat function may require yielding control
472  * back to the interpreter.
473  *
474  * To simplify the calling conventions, this function is provided to first push a
475  * resumption stack frame for the module, and then push a tmpl stack frame.
476  *
477  * After pushing those frames the function updates the stack pointer to jump over
478  * the resumption frame and execute the tmpl expansion.
479  *
480  * When the tmpl interpreter finishes, and pops the tmpl frame, the unlang interpreter
481  * will then call the module resumption frame, allowing the module to continue execution.
482  *
483  * @param[in] ctx To allocate talloc value boxes and values in.
484  * @param[out] out Where to write the result of the expansion.
485  * @param[in] request The current request.
486  * @param[in] vpt the tmpl to expand
487  * @param[in] args Arguments which control how to evaluate the various
488  * types of xlats.
489  * @param[in] resume function to call when the XLAT expansion is complete.
490  * @param[in] signal function to call if a signal is received.
491  * @param[in] sigmask Signals to block.
492  * @param[in] rctx to pass to the resume() and signal() callbacks.
493  * @return
494  * - UNLANG_ACTION_PUSHED_CHILD
495  */
496 unlang_action_t unlang_module_yield_to_tmpl(TALLOC_CTX *ctx, fr_value_box_list_t *out,
497  request_t *request, tmpl_t const *vpt,
499  module_method_t resume,
500  unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
501 {
502  /*
503  * Push the resumption point BEFORE pushing the xlat onto
504  * the parents stack.
505  */
506  (void) unlang_module_yield(request, resume, signal, sigmask, rctx);
507 
508  /*
509  * Push the xlat function
510  */
511  if (unlang_tmpl_push(ctx, out, request, vpt, args) < 0) return UNLANG_ACTION_FAIL;
512 
514 }
515 
517  request_t *request, CONF_SECTION *subcs,
518  rlm_rcode_t default_rcode,
519  module_method_t resume,
520  unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
521 {
522  if (!subcs) {
523  unlang_stack_t *stack = request->stack;
524  unlang_stack_frame_t *frame = &stack->frame[stack->depth];
525  unlang_module_t *mc;
527 
530 
531  /*
532  * Be transparent to the resume function.
533  * frame->result will be overwritten
534  * anyway when we return.
535  */
536  stack->result = frame->result = default_rcode;
537  state = talloc_get_type_abort(frame->state, unlang_frame_state_module_t);
538 
539  return resume(p_result,
541  state->env_data, rctx),
542  request);
543  }
544 
545  /*
546  * Push the resumption point BEFORE adding the subsection
547  * to the parents stack.
548  */
549  (void) unlang_module_yield(request, resume, signal, sigmask, rctx);
550 
551  if (unlang_interpret_push_section(request, subcs,
552  default_rcode, UNLANG_SUB_FRAME) < 0) return UNLANG_ACTION_STOP_PROCESSING;
553 
555 }
556 
557 /** Yield a request back to the interpreter from within a module
558  *
559  * This passes control of the request back to the unlang interpreter, setting
560  * callbacks to execute when the request is 'signalled' asynchronously, or whatever
561  * timer or I/O event the module was waiting for occurs.
562  *
563  * @note The module function which calls #unlang_module_yield should return control
564  * of the C stack to the unlang interpreter immediately after calling #unlang_module_yield.
565  * A common pattern is to use ``return unlang_module_yield(...)``.
566  *
567  * @param[in] request The current request.
568  * @param[in] resume Called on unlang_interpret_mark_runnable().
569  * @param[in] signal Called on unlang_action().
570  * @param[in] sigmask Set of signals to block.
571  * @param[in] rctx to pass to the callbacks.
572  * @return
573  * - UNLANG_ACTION_YIELD.
574  */
576  module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
577 {
578  unlang_stack_t *stack = request->stack;
579  unlang_stack_frame_t *frame = &stack->frame[stack->depth];
580  unlang_frame_state_module_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_module_t);
581 
582  REQUEST_VERIFY(request); /* Check the yielded request is sane */
583 
584  state->rctx = rctx;
585  state->resume = resume;
586  state->signal = signal;
587  state->sigmask = sigmask;
588 
589  /*
590  * We set the repeatable flag here,
591  * so that the resume function is always
592  * called going back up the stack.
593  */
595 
596  return UNLANG_ACTION_YIELD;
597 }
598 
599 /*
600  * Lock the mutex for the module
601  */
602 static inline CC_HINT(always_inline) void safe_lock(module_instance_t *mi)
603 {
604  if ((mi->module->flags & MODULE_TYPE_THREAD_UNSAFE) != 0) pthread_mutex_lock(&mi->mutex);
605 }
606 
607 /*
608  * Unlock the mutex for the module
609  */
610 static inline CC_HINT(always_inline) void safe_unlock(module_instance_t *mi)
611 {
612  if ((mi->module->flags & MODULE_TYPE_THREAD_UNSAFE) != 0) pthread_mutex_unlock(&mi->mutex);
613 }
614 
615 /** Send a signal (usually stop) to a request
616  *
617  * This is typically called via an "async" action, i.e. an action
618  * outside of the normal processing of the request.
619  *
620  * If there is no #unlang_module_signal_t callback defined, the action is ignored.
621  *
622  * @param[in] request The current request.
623  * @param[in] frame current stack frame.
624  * @param[in] action to signal.
625  */
626 static void unlang_module_signal(request_t *request, unlang_stack_frame_t *frame, fr_signal_t action)
627 {
628  unlang_frame_state_module_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_module_t);
630  char const *caller;
631 
632  if (!state->signal) return;
633 
634  /*
635  * Async calls can't push anything onto the unlang stack, so we just use a local "caller" here.
636  */
637  caller = request->module;
638  request->module = mc->instance->name;
639  safe_lock(mc->instance);
640  if (!(action & state->sigmask)) state->signal(MODULE_CTX(mc->instance->dl_inst, state->thread->data, state->env_data, state->rctx), request, action);
641  safe_unlock(mc->instance);
642  request->module = caller;
643 
644  /*
645  * One fewer caller for this module. Since this module
646  * has been cancelled, decrement the active callers and
647  * ignore any future signals.
648  */
649  if (action == FR_SIGNAL_CANCEL) {
650  state->thread->active_callers--;
651  state->signal = NULL;
652  }
653 }
654 
655 /** Cleanup after a module completes
656  *
657  */
659 {
660  unlang_frame_state_module_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_module_t);
661  rlm_rcode_t rcode = state-> set_rcode ? state->rcode : *p_result;
662 
663 #ifndef NDEBUG
664  fr_assert(state->unlang_indent == request->log.indent.unlang);
665 #endif
666 
667  fr_assert(rcode >= RLM_MODULE_REJECT);
668  fr_assert(rcode < RLM_MODULE_NOT_SET);
669 
670  RDEBUG("%s (%s)", frame->instruction->name ? frame->instruction->name : "",
671  fr_table_str_by_value(mod_rcode_table, rcode, "<invalid>"));
672 
673  if (state->p_result) *state->p_result = rcode; /* Inform our caller if we have one */
674  *p_result = rcode;
675  request->module = state->previous_module;
676 
678 }
679 
680 /** Cleanup after a yielded module completes
681  *
682  */
684 {
685  unlang_frame_state_module_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_module_t);
686 
687  state->thread->active_callers--;
688 
689  return unlang_module_done(p_result, request, frame);
690 }
691 
692 /** Wrapper to call a module's resumption function
693  *
694  * This is called _after_ the module first yields, and again after any
695  * other yields.
696  */
698 {
699  unlang_frame_state_module_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_module_t);
701  module_method_t resume;
702  unlang_action_t ua;
703 
704  /*
705  * Update the rcode from any child calls that
706  * may have been performed. The module still
707  * has a chance to override this rcode if it
708  * wants, but process modules in particular
709  * expect to see the result of child
710  * evaluations available to them in p_result.
711  */
712  state->rcode = *p_result < RLM_MODULE_NUMCODES ? *p_result : RLM_MODULE_NOOP;
713 
714  fr_assert(state->resume != NULL);
715 
716  resume = state->resume;
717 
718  /*
719  * The module *MUST* explicitly set the resume
720  * function when yielding or pushing children
721  * if it wants to be called again later.
722  */
723  state->resume = NULL;
724 
725  /*
726  * Lock is noop unless instance->mutex is set.
727  */
728  safe_lock(mc->instance);
729  ua = resume(&state->rcode, MODULE_CTX(mc->instance->dl_inst, state->thread->data,
730  state->env_data, state->rctx), request);
731  safe_unlock(mc->instance);
732 
733  if (request->master_state == REQUEST_STOP_PROCESSING) ua = UNLANG_ACTION_STOP_PROCESSING;
734 
735  switch (ua) {
737  RWARN("Module %s or worker signalled to stop processing request", mc->instance->module->name);
738  if (state->p_result) *state->p_result = state->rcode;
739  state->thread->active_callers--;
740  *p_result = state->rcode;
741  request->module = state->previous_module;
743 
744  case UNLANG_ACTION_YIELD:
745  /*
746  * The module yielded but didn't set a
747  * resume function, this means it's done
748  * and when the I/O operation completes
749  * it shouldn't be called again.
750  */
751  if (!state->resume) {
753  } else {
754  repeatable_set(frame);
755  }
756  return UNLANG_ACTION_YIELD;
757 
758  /*
759  * The module is done (for now).
760  * But, running it pushed one or more asynchronous
761  * calls onto the stack for evaluation.
762  * These need to be run before the module resumes
763  * or the next unlang instruction is processed.
764  */
766  /*
767  * The module pushed a child and didn't
768  * set a resume function, this means
769  * it's done, and we won't call it again
770  * but we still need to do some cleanup
771  * after the child returns.
772  */
773  if (!state->resume) {
775  state->set_rcode = false; /* Preserve the child rcode */
776  } else {
777  repeatable_set(frame);
778  }
780 
782  /*
783  * Module set a resume function but
784  * didn't yield or push additional
785  * children.
786  *
787  * Evaluate the function now and
788  * use the result as the final result.
789  */
790  if (state->resume) return unlang_module_resume(p_result, request, frame);
791  request->module = state->previous_module;
792  break;
793 
795  request->module = state->previous_module;
796  break;
797 
798  case UNLANG_ACTION_FAIL:
799  *p_result = RLM_MODULE_FAIL;
800  request->module = state->previous_module;
801  break;
802 
803  case UNLANG_ACTION_EXECUTE_NEXT: /* Not valid */
804  fr_assert(0);
805  *p_result = RLM_MODULE_FAIL;
806  break;
807  }
808 
809  unlang_module_resume_done(p_result, request, frame);
810  request->module = state->previous_module;
811 
812  return ua;
813 }
814 
815 /** Call the callback registered for a retry event
816  *
817  * @param[in] el the event timer was inserted into.
818  * @param[in] now The current time, as held by the event_list.
819  * @param[in] ctx the stack frame
820  *
821  */
823 {
824  request_t *request = talloc_get_type_abort(ctx, request_t);
825  unlang_stack_t *stack = request->stack;
826  unlang_stack_frame_t *frame = &stack->frame[stack->depth];
827  unlang_frame_state_module_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_module_t);
828 
829  /*
830  * The module will get either a RETRY signal, or a
831  * TIMEOUT signal (also for max count).
832  *
833  * The signal handler should generally change the resume
834  * function, and mark the request as runnable. We
835  * probably don't want the module to do tons of work in
836  * the signal handler, as it's called from the event
837  * loop. And doing so could affect the other event
838  * timers.
839  *
840  * Note also that we call frame->signal(), and not
841  * unlang_interpret_signal(). That is because we want to
842  * signal only the module. We know that the other frames
843  * on the stack can't handle this particular signal. So
844  * there's no point in calling them. Or, if sections
845  * have their own retry handlers, then we don't want to
846  * signal those _other_ retry handles with _our_ signal.
847  */
848  switch (fr_retry_next(&state->retry, now)) {
849  case FR_RETRY_CONTINUE:
850  frame->signal(request, frame, FR_SIGNAL_RETRY);
851 
852  /*
853  * Reset the timer.
854  */
855  if (fr_event_timer_at(request, unlang_interpret_event_list(request), &state->ev, state->retry.next,
856  unlang_module_event_retry_handler, request) < 0) {
857  RPEDEBUG("Failed inserting event");
858  unlang_interpret_mark_runnable(request); /* and let the caller figure out what's up */
859  }
860  return;
861 
862  case FR_RETRY_MRD:
863  REDEBUG("Reached max_rtx_duration (%pVs > %pVs) - sending timeout signal",
865  break;
866 
867  case FR_RETRY_MRC:
868  REDEBUG("Reached max_rtx_count (%u > %u) - sending timeout signal",
869  state->retry.count, state->retry.config->mrc);
870  break;
871  }
872 
873  frame->signal(request, frame, FR_SIGNAL_TIMEOUT);
874 }
875 
877 {
878  unlang_module_t *mc;
879  unlang_frame_state_module_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_module_t);
880  unlang_action_t ua;
881  fr_time_t now = fr_time_wrap(0);
882 
883  *p_result = state->rcode = RLM_MODULE_NOOP;
884  state->set_rcode = true;
885  state->previous_module = request->module;
886 
887 #ifndef NDEBUG
888  state->unlang_indent = request->log.indent.unlang;
889 #endif
890  /*
891  * Process a stand-alone child, and fall through
892  * to dealing with it's parent.
893  */
895  fr_assert(mc);
896 
897  RDEBUG4("[%i] %s - %s (%s)", stack_depth_current(request), __FUNCTION__,
898  mc->instance->name, mc->instance->module->name);
899 
900  state->p_result = NULL;
901 
902  /*
903  * Return administratively configured return code
904  */
905  if (mc->instance->force) {
906  state->rcode = mc->instance->code;
908  goto done;
909  }
910 
911  if (mc->call_env) {
912  if (!state->env_data) {
913  ua = call_env_expand(state, request, &state->env_result, &state->env_data, mc->call_env);
914  switch (ua) {
915  case UNLANG_ACTION_FAIL:
916  goto fail;
917 
919  frame_repeat(frame, unlang_module);
921 
922  default:
923  break;
924  }
925  }
926 
927  /*
928  * Fail the module call on callenv failure
929  */
931  }
932 
933  /*
934  * Grab the thread/module specific data if any exists.
935  */
936  state->thread = module_thread(mc->instance);
937  fr_assert(state->thread != NULL);
938 
939  /*
940  * Don't allow returning _through_ modules
941  */
943 
944  /*
945  * For logging unresponsive children.
946  */
947  state->thread->total_calls++;
948 
949  /*
950  * If we're doing retries, remember when we started
951  * running the module.
952  */
953  if (fr_time_delta_ispos(frame->instruction->actions.retry.irt)) now = fr_time();
954 
955  request->module = mc->instance->name;
956  safe_lock(mc->instance); /* Noop unless instance->mutex set */
957  ua = mc->method(&state->rcode,
958  MODULE_CTX(mc->instance->dl_inst, state->thread->data, state->env_data, NULL),
959  request);
960  safe_unlock(mc->instance);
961 
962  if (request->master_state == REQUEST_STOP_PROCESSING) ua = UNLANG_ACTION_STOP_PROCESSING;
963 
964  switch (ua) {
965  /*
966  * It is now marked as "stop" when it wasn't before, we
967  * must have been blocked.
968  */
970  RWARN("Module %s became unblocked", mc->instance->module->name);
971  if (state->p_result) *state->p_result = state->rcode;
972  *p_result = state->rcode;
973  request->module = state->previous_module;
975 
976  case UNLANG_ACTION_YIELD:
977  state->thread->active_callers++;
978 
979  /*
980  * The module yielded but didn't set a
981  * resume function, this means it's done
982  * and when the I/O operation completes
983  * it shouldn't be called again.
984  */
985  if (!state->resume) {
987  } else {
989  }
990 
991  /*
992  * If we have retry timers, then start the retries.
993  */
996 
997  fr_retry_init(&state->retry, now, &frame->instruction->actions.retry);
998 
999  if (fr_event_timer_at(request, unlang_interpret_event_list(request),
1000  &state->ev, state->retry.next,
1001  unlang_module_event_retry_handler, request) < 0) {
1002  RPEDEBUG("Failed inserting event");
1003  goto fail;
1004  }
1005  }
1006 
1007  return UNLANG_ACTION_YIELD;
1008 
1009  /*
1010  * The module is done (for now).
1011  * But, running it pushed one or more asynchronous
1012  * calls onto the stack for evaluation.
1013  * These need to be run before the module resumes
1014  * or the next unlang instruction is processed.
1015  */
1017  /*
1018  * The module pushed a child and didn't
1019  * set a resume function, this means
1020  * it's done, and we won't call it again
1021  * but we still need to do some cleanup
1022  * after the child returns.
1023  */
1024  if (!state->resume) {
1026  state->set_rcode = false; /* Preserve the child rcode */
1027  } else {
1028  repeatable_set(frame);
1029  }
1031 
1033  /*
1034  * Module set a resume function but
1035  * didn't yield or push additional
1036  * children.
1037  *
1038  * Evaluate the function now and
1039  * use the result as the final result.
1040  */
1041  if (state->resume) {
1042  frame->process = unlang_module_resume; /* unlang_module_resume will assume this is set */
1043  return unlang_module_resume(p_result, request, frame);
1044  }
1045  break;
1046 
1047  case UNLANG_ACTION_UNWIND:
1048  break;
1049 
1050  case UNLANG_ACTION_FAIL:
1051  fail:
1052  *p_result = RLM_MODULE_FAIL;
1053  break;
1054 
1056  fr_assert(0);
1057  *p_result = RLM_MODULE_FAIL;
1058  break;
1059  }
1060 
1061 done:
1062  request->module = state->previous_module;
1063  unlang_module_done(p_result, request, frame);
1064  return ua;
1065 }
1066 
1068 {
1070  &(unlang_op_t){
1071  .name = "module",
1072  .interpret = unlang_module,
1073  .signal = unlang_module_signal,
1074  .frame_state_size = sizeof(unlang_frame_state_module_t),
1075  .frame_state_type = "unlang_frame_state_module_t",
1076  });
1077 }
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
@ UNLANG_ACTION_UNWIND
Break out of the current group.
Definition: action.h:41
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
Definition: action.h:39
@ UNLANG_ACTION_EXECUTE_NEXT
Execute the next unlang_t.
Definition: action.h:38
@ UNLANG_ACTION_STOP_PROCESSING
Break out of processing the current request (unwind).
Definition: action.h:43
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
Definition: action.h:36
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition: action.h:37
@ 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:444
#define UNUSED
Definition: build.h:313
unlang_action_t call_env_expand(TALLOC_CTX *ctx, request_t *request, call_env_result_t *env_result, void **env_data, call_env_t const *call_env)
Initialise the expansion of a call environment.
Definition: call_env.c:287
@ CALL_ENV_SUCCESS
Definition: call_env.h:50
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
fr_table_num_sorted_t const mod_rcode_table[]
Definition: compile.c:72
fr_retry_config_t retry
Definition: compile.h:38
A module/inst tuple.
Definition: dl_module.h:162
#define fr_event_fd_insert(...)
Definition: event.h:232
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
Definition: event.h:62
#define fr_event_timer_at(...)
Definition: event.h:250
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_mark_runnable(request_t *request)
Mark a request as resumable.
Definition: interpret.c:1340
int unlang_interpret_push(request_t *request, unlang_t const *instruction, rlm_rcode_t default_rcode, bool do_next_sibling, bool top_frame)
Push a new frame onto the stack.
Definition: interpret.c:161
int unlang_interpret_push_section(request_t *request, CONF_SECTION *cs, rlm_rcode_t default_rcode, bool top_frame)
Push a configuration section onto the request stack for later interpretation.
Definition: interpret.c:982
#define UNLANG_SUB_FRAME
Definition: interpret.h:36
#define RWARN(fmt,...)
Definition: log.h:297
#define RPEDEBUG(fmt,...)
Definition: log.h:376
#define RDEBUG4(fmt,...)
Definition: log.h:344
void unlang_register(int type, unlang_op_t *op)
Register an operation with the interpreter.
Definition: base.c:65
talloc_free(reap)
int fr_event_timer_delete(fr_event_timer_t const **ev_p)
Delete a timer event from the event list.
Definition: event.c:1604
int fr_event_fd_delete(fr_event_list_t *el, int fd, fr_event_filter_t filter)
Remove a file descriptor from the event loop.
Definition: event.c:1253
Stores all information relating to an event list.
Definition: event.c:411
A timer event.
Definition: event.c:102
static char * stack[MAX_STACK]
Definition: radmin.c:158
#define MODULE_CTX(_dl_inst, _thread, _env_data, _rctx)
Wrapper to create a module_ctx_t as a compound literal.
Definition: module_ctx.h:123
Declarations for the unlang module interface.
static unlang_module_t * unlang_generic_to_module(unlang_t const *p)
Definition: module_priv.h:89
fr_event_timer_t const * ev
retry timer just for this module.
Definition: module_priv.h:82
rlm_rcode_t rcode
the result, only for unlang_module_resume_final.
Definition: module_priv.h:64
module_method_t resume
resumption handler
Definition: module_priv.h:73
module_instance_t * instance
Global instance of the module we're calling.
Definition: module_priv.h:37
static unlang_t * unlang_module_to_generic(unlang_module_t *p)
Definition: module_priv.h:95
char const * previous_module
old request->module
Definition: module_priv.h:47
fr_signal_t sigmask
Signals to block.
Definition: module_priv.h:75
bool set_rcode
Overwrite the current rcode for the section with the module rcode.
Definition: module_priv.h:65
call_env_result_t env_result
Result of the previous call environment expansion.
Definition: module_priv.h:53
fr_retry_t retry
retry timers, etc.
Definition: module_priv.h:83
void * env_data
Expanded per call "call environment" tmpls.
Definition: module_priv.h:54
rlm_rcode_t * p_result
Where to store the result.
Definition: module_priv.h:63
module_thread_instance_t * thread
thread-local data for this module.
Definition: module_priv.h:48
unlang_t self
Common fields in all unlang_t tree nodes.
Definition: module_priv.h:36
unlang_module_signal_t signal
for signal handlers
Definition: module_priv.h:74
int unlang_indent
Record what this was when we entered the module.
Definition: module_priv.h:57
module_method_t method
The entry point into the module.
Definition: module_priv.h:38
void * rctx
for resume / signal
Definition: module_priv.h:72
call_env_t const * call_env
The per call parsed call environment.
Definition: module_priv.h:39
A module stack entry.
Definition: module_priv.h:46
A call to a module method.
Definition: module_priv.h:35
static bool done
Definition: radclient.c:80
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG(fmt,...)
Definition: radclient.h:53
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
@ RLM_MODULE_INVALID
The module considers the request invalid.
Definition: rcode.h:45
@ RLM_MODULE_OK
The module is OK, continue.
Definition: rcode.h:43
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition: rcode.h:42
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
Definition: rcode.h:46
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition: rcode.h:41
@ RLM_MODULE_NOTFOUND
User not found.
Definition: rcode.h:47
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition: rcode.h:49
@ RLM_MODULE_NOT_SET
Error resolving rcode (should not be returned by modules).
Definition: rcode.h:51
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition: rcode.h:48
@ RLM_MODULE_NUMCODES
How many valid return codes there are.
Definition: rcode.h:50
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition: rcode.h:44
#define REQUEST_VERIFY(_x)
Definition: request.h:275
@ REQUEST_STOP_PROCESSING
Definition: request.h:62
void * request_data_get(request_t *request, void const *unique_ptr, int unique_int)
Get opaque data from a request.
Definition: request_data.c:292
#define request_data_talloc_add(_request, _unique_ptr, _unique_int, _type, _opaque, _free_on_replace, _free_on_parent, _persist)
Add opaque data to a request_t.
Definition: request_data.h:86
char const * name
Instance name e.g. user_database.
Definition: module.h:181
@ MODULE_TYPE_THREAD_UNSAFE
Module is not threadsafe.
Definition: module.h:50
uint64_t active_callers
total number of times we've been called
Definition: module.h:227
bool force
Force the module to return a specific code.
Definition: module.h:200
dl_module_inst_t * dl_inst
Structure containing the module's instance data, configuration, and dl handle.
Definition: module.h:183
void * data
Thread specific instance data.
Definition: module.h:220
rlm_rcode_t code
Code module will return when 'force' has has been set to true.
Definition: module.h:203
int flags
Definition: module.h:147
module_t const * module
Public module structure.
Definition: module.h:188
unlang_action_t(* module_method_t)(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Module section callback.
Definition: module.h:69
pthread_mutex_t mutex
Used prevent multiple threads entering a thread unsafe module simultaneously.
Definition: module.h:192
Per instance data.
Definition: module.h:169
static fr_slen_t vpt
Definition: tmpl.h:1260
fr_signal_t
Definition: signal.h:48
module_thread_instance_t * module_thread(module_instance_t *mi)
Retrieve module/thread specific instance for a module.
Definition: module.c:459
static void unlang_module_event_timeout_handler(UNUSED fr_event_list_t *el, fr_time_t now, void *ctx)
Call the callback registered for a timeout event.
Definition: module.c:105
unlang_action_t unlang_module_yield_to_section(rlm_rcode_t *p_result, request_t *request, CONF_SECTION *subcs, rlm_rcode_t default_rcode, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Definition: module.c:516
int unlang_module_set_resume(request_t *request, module_method_t resume)
Change the resume function of a module.
Definition: module.c:400
unlang_module_fd_event_t fd_read
Function to call when FD is readable.
Definition: module.c:46
static unlang_action_t unlang_module(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Definition: module.c:876
void * env_data
Per call environment data.
Definition: module.c:52
static void unlang_event_fd_error_handler(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, UNUSED int fd_errno, void *ctx)
Call the callback registered for an I/O error event.
Definition: module.c:210
request_t * request
Request this event pertains to.
Definition: module.c:43
int unlang_module_fd_add(request_t *request, unlang_module_fd_event_t read, unlang_module_fd_event_t write, unlang_module_fd_event_t error, void const *rctx, int fd)
Set a callback for the request.
Definition: module.c:245
static int _unlang_event_free(unlang_module_event_t *ev)
Frees an unlang event, removing it from the request's event loop.
Definition: module.c:81
int unlang_module_timeout_delete(request_t *request, void const *ctx)
Delete a previously set timeout callback.
Definition: module.c:176
unlang_action_t unlang_module_yield_to_xlat(TALLOC_CTX *ctx, bool *p_success, fr_value_box_list_t *out, request_t *request, xlat_exp_head_t const *exp, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Push a pre-compiled xlat and resumption state onto the stack for evaluation.
Definition: module.c:449
static void unlang_event_fd_write_handler(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *ctx)
Call the callback registered for a write I/O event.
Definition: module.c:194
static void safe_lock(module_instance_t *mi)
Definition: module.c:602
int fd
File descriptor to wait on.
Definition: module.c:44
unlang_module_timeout_t timeout
Function to call on timeout.
Definition: module.c:45
dl_module_inst_t * dl_inst
Module instance to pass to callbacks.
Definition: module.c:49
unlang_module_fd_event_t fd_error
Function to call when FD has errored.
Definition: module.c:48
unlang_action_t unlang_module_yield(request_t *request, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
Definition: module.c:575
void unlang_module_init(void)
Definition: module.c:1067
void * thread
Thread specific module instance.
Definition: module.c:51
static unlang_action_t unlang_module_resume(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Wrapper to call a module's resumption function.
Definition: module.c:697
static unlang_action_t unlang_module_resume_done(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Cleanup after a yielded module completes.
Definition: module.c:683
static unlang_action_t unlang_module_done(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Cleanup after a module completes.
Definition: module.c:658
static void unlang_module_event_retry_handler(UNUSED fr_event_list_t *el, fr_time_t now, void *ctx)
Call the callback registered for a retry event.
Definition: module.c:822
fr_event_timer_t const * ev
Event in this worker's event heap.
Definition: module.c:54
int unlang_module_push(rlm_rcode_t *p_result, request_t *request, module_instance_t *module_instance, module_method_t method, bool top_frame)
Push a module or submodule onto the stack for evaluation.
Definition: module.c:325
int unlang_module_timeout_add(request_t *request, unlang_module_timeout_t callback, void const *rctx, fr_time_t when)
Set a timeout for the request.
Definition: module.c:128
static void unlang_event_fd_read_handler(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *ctx)
Call the callback registered for a read I/O event.
Definition: module.c:66
unlang_action_t unlang_module_yield_to_tmpl(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, tmpl_t const *vpt, unlang_tmpl_args_t *args, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Push a pre-compiled tmpl and resumption state onto the stack for evaluation.
Definition: module.c:496
static void safe_unlock(module_instance_t *mi)
Definition: module.c:610
unlang_module_fd_event_t fd_write
Function to call when FD is writable.
Definition: module.c:47
void const * rctx
rctx data to pass to callbacks.
Definition: module.c:53
static void unlang_module_signal(request_t *request, unlang_stack_frame_t *frame, fr_signal_t action)
Send a signal (usually stop) to a request.
Definition: module.c:626
int unlang_module_fd_delete(request_t *request, void const *ctx, int fd)
Delete a previously set file descriptor callback.
Definition: module.c:302
Wrap an fr_event_timer_t providing data needed for unlang events.
Definition: module.c:42
RETURN_MODULE_FAIL
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition: state_test.c:8
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition: table.h:253
#define fr_time_wrap(_time)
Definition: time.h:145
#define fr_time_delta_ispos(_a)
Definition: time.h:288
#define fr_time_gt(_a, _b)
Definition: time.h:237
#define fr_time_sub(_a, _b)
Subtract one time from another.
Definition: time.h:229
"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:259
static fr_event_list_t * el
void(* unlang_module_fd_event_t)(module_ctx_t const *mctx, request_t *request, int fd)
A callback when the FD is ready for reading.
Definition: module.h:65
void(* unlang_module_signal_t)(module_ctx_t const *mctx, request_t *request, fr_signal_t action)
A callback when the request gets a fr_signal_t.
Definition: module.h:79
void(* unlang_module_timeout_t)(module_ctx_t const *mctx, request_t *request, fr_time_t fired)
A callback when the the timeout occurs.
Definition: module.h:51
Functions to allow tmpls to push resumption frames onto the stack and inform the interpreter about th...
Arguments for evaluating different types of tmpls.
Definition: tmpl.h:47
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
unlang_signal_t signal
function to call when signalling this stack frame
Definition: unlang_priv.h:293
void * state
Stack frame specialisations.
Definition: unlang_priv.h:304
#define UNLANG_NEXT_STOP
Definition: unlang_priv.h:102
#define MOD_ACTION_RETURN
Definition: unlang_priv.h:44
static void return_point_set(unlang_stack_frame_t *frame)
Definition: unlang_priv.h:356
unlang_actions_t actions
Priorities, etc. for the various return codes.
Definition: unlang_priv.h:131
char const * name
Unknown...
Definition: unlang_priv.h:125
static int stack_depth_current(request_t *request)
Definition: unlang_priv.h:401
@ UNLANG_TYPE_MODULE
Module method.
Definition: unlang_priv.h:56
static void frame_repeat(unlang_stack_frame_t *frame, unlang_process_t process)
Mark the current stack frame up for repeat, and set a new process function.
Definition: unlang_priv.h:526
unlang_t const * instruction
The unlang node we're evaluating.
Definition: unlang_priv.h:289
static bool is_yielded(unlang_stack_frame_t const *frame)
Definition: unlang_priv.h:369
rlm_rcode_t result
The result from executing the instruction.
Definition: unlang_priv.h:308
static void repeatable_set(unlang_stack_frame_t *frame)
Definition: unlang_priv.h:353
unlang_process_t process
function to call for interpreting this stack frame
Definition: unlang_priv.h:292
unlang_type_t type
The specialisation of this node.
Definition: unlang_priv.h:127
static unlang_stack_frame_t * frame_current(request_t *request)
Definition: unlang_priv.h:394
An unlang operation.
Definition: unlang_priv.h:214
Our interpreter stack, as distinct from the C stack.
Definition: unlang_priv.h:288
An unlang stack associated with a request.
Definition: unlang_priv.h:322
fr_retry_state_t fr_retry_next(fr_retry_t *r, fr_time_t now)
Initialize a retransmission counter.
Definition: retry.c:84
void fr_retry_init(fr_retry_t *r, fr_time_t now, fr_retry_config_t const *config)
Initialize a retransmission counter.
Definition: retry.c:36
fr_time_t start
when we started the retransmission
Definition: retry.h:43
fr_time_delta_t irt
Initial transmission time.
Definition: retry.h:33
#define RETRY_INIT
Definition: retry.h:39
uint32_t mrc
Maximum retransmission count.
Definition: retry.h:36
fr_retry_config_t const * config
master configuration
Definition: retry.h:42
@ FR_RETRY_MRC
reached maximum retransmission count
Definition: retry.h:57
@ FR_RETRY_CONTINUE
Definition: retry.h:56
@ FR_RETRY_MRD
reached maximum retransmission duration
Definition: retry.h:58
uint32_t count
number of sent packets
Definition: retry.h:47
fr_time_delta_t mrd
Maximum retransmission duration.
Definition: retry.h:35
fr_time_t next
when the next timer should be set
Definition: retry.h:44
#define fr_box_time_delta(_val)
Definition: value.h:336
static size_t char ** out
Definition: value.h:984