The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
subrequest.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: 06fb3ba4fa974b3569dfec812b2b9494c65490ef $
19 *
20 * @file unlang/subrequest.c
21 * @brief Unlang "subrequest" and "detach" keyword evaluation.
22 *
23 * @copyright 2006-2019 The FreeRADIUS server project
24 */
25
26RCSID("$Id: 06fb3ba4fa974b3569dfec812b2b9494c65490ef $")
27
28#include <freeradius-devel/server/state.h>
29#include <freeradius-devel/server/tmpl_dcursor.h>
30#include <freeradius-devel/server/request.h>
31#include <freeradius-devel/unlang/action.h>
32#include "unlang_priv.h"
33#include "interpret_priv.h"
34#include "subrequest_priv.h"
35#include "child_request_priv.h"
36
37/** Send a signal from parent request to subrequest
38 *
39 */
41{
42 unlang_child_request_t *cr = talloc_get_type_abort(frame->state, unlang_child_request_t);
43 request_t *child = talloc_get_type_abort(cr->request, request_t);
44
45 switch (cr->state) {
46 case CHILD_DETACHED:
47 RDEBUG3("subrequest detached during its execution - Not sending signal to child");
48 return;
49
50 case CHILD_CANCELLED:
51 RDEBUG3("subrequest is cancelled - Not sending signal to child");
52 return;
53
54 default:
55 break;
56 }
57
58 /*
59 * Parent should never receive a detach
60 * signal whilst the child is running.
61 *
62 * Only the child receives a detach
63 * signal when the detach keyword is used.
64 */
65 fr_assert(action != FR_SIGNAL_DETACH);
66
67 /*
68 * If the server is stopped, inside a breakpoint,
69 * whilst processing a child, on resumption both
70 * requests (parent and child) may need to be
71 * cancelled as they've both hit max request_time.
72 *
73 * Sometimes the child will run to completion before
74 * the cancellation is processed, but the parent
75 * will still be cancelled.
76 *
77 * When the parent is cancelled this function is
78 * executed, which will signal an already stopped
79 * child to cancel itself.
80 *
81 * This triggers asserts in the time tracking code.
82 *
83 * ...so we check to see if the child is done before
84 * sending a signal.
85 */
86 if (unlang_request_is_done(child)) return;
87
88 /*
89 * Forward other signals to the child
90 */
91 unlang_interpret_signal(child, action);
92}
93
94/** Parent being resumed after a child completes
95 *
96 */
99{
101 unlang_child_request_t *cr = talloc_get_type_abort(frame->state, unlang_child_request_t);
102 request_t *child = cr->request;
104
105 /*
106 * Child detached
107 */
108 if (cr->state == CHILD_DETACHED) {
109 RDEBUG3("subrequest detached during its execution - Not updating rcode or reply attributes");
110
111 /*
112 * If the child detached the subrequest section
113 * should become entirely transparent, and
114 * should not update the section rcode.
115 */
117 }
118
119 RDEBUG3("subrequest completeed with rcode %s",
120 fr_table_str_by_value(mod_rcode_table, cr->result.rcode, "<invalid>"));
121
122 *p_result = cr->result.rcode;
123 frame->priority = cr->result.priority;
124
125 /*
126 * If there's a no destination tmpl, we're done.
127 */
128 if (!child->reply) {
131 }
132
133 /*
134 * Otherwise... copy reply attributes into the
135 * specified destination.
136 */
138 if (gext->dst) {
139 fr_pair_t *vp = NULL;
141 fr_dcursor_t cursor;
142
143 /*
144 * Use callback to build missing destination container.
145 */
146 vp = tmpl_dcursor_build_init(NULL, request, &cc, &cursor, request, gext->dst, tmpl_dcursor_pair_build, NULL);
147 if (!vp) {
148 RPDEBUG("Discarding subrequest attributes - Failed allocating groups");
149 *p_result = RLM_MODULE_FAIL;
152 }
153
154 MEM(fr_pair_list_copy(vp, &vp->vp_group, &child->reply_pairs) >= 0);
155
157 }
158
161}
162
163/** Allocates a new subrequest and initialises it
164 *
165 */
167{
168 unlang_child_request_t *cr = talloc_get_type_abort(frame->state, unlang_child_request_t);
169 request_t *child;
170 fr_pair_t *vp;
171
174
175 /*
176 * This should only be set for manually pushed subrequests
177 */
178 fr_assert(!cr->config.free_child);
179
180 /*
181 * Initialize the state
182 */
184 if (!g->num_children) {
185 *p_result = RLM_MODULE_NOOP;
187 }
188
190 child = unlang_io_subrequest_alloc(request, gext->dict, UNLANG_DETACHABLE);
191 if (!child) {
192 fail:
193 *p_result = cr->result.rcode = RLM_MODULE_FAIL;
194 if (cr->result.p_result) *cr->result.p_result = *p_result;
196 }
197 /*
198 * Set the packet type.
199 */
200 MEM(vp = fr_pair_afrom_da(child->request_ctx, gext->attr_packet_type));
201 if (gext->type_enum) {
202 child->packet->code = vp->vp_uint32 = gext->type_enum->value->vb_uint32;
203 } else {
204 fr_dict_enum_value_t const *type_enum;
205 fr_pair_t *attr;
206
207 if (tmpl_find_vp(&attr, request, gext->vpt) < 0) {
208 RDEBUG("Failed finding attribute %s", gext->vpt->name);
209 goto fail;
210 }
211
212 if (tmpl_attr_tail_da(gext->vpt)->type == FR_TYPE_STRING) {
213 type_enum = fr_dict_enum_by_name(gext->attr_packet_type, attr->vp_strvalue, attr->vp_length);
214 if (!type_enum) {
215 RDEBUG("Unknown Packet-Type %pV", &attr->data);
216 goto fail;
217 }
218
219 child->packet->code = vp->vp_uint32 = type_enum->value->vb_uint32;
220 } else {
221 fr_value_box_t box;
222
223 fr_value_box_init(&box, FR_TYPE_UINT32, NULL, false);
224 if (fr_value_box_cast(request, &box, FR_TYPE_UINT32, NULL, &attr->data) < 0) {
225 RDEBUG("Failed casting value from %pV to data type uint32", &attr->data);
226 goto fail;
227 }
228
229 /*
230 * Check that the value is known to the server.
231 *
232 * If it isn't known, then there's no
233 * "recv foo" section for it and we can't
234 * do anything with this packet.
235 */
236 type_enum = fr_dict_enum_by_value(gext->attr_packet_type, &box);
237 if (!type_enum) {
238 RDEBUG("Invalid value %pV for Packet-Type", &box);
239 goto fail;
240 }
241
242 child->packet->code = vp->vp_uint32 = box.vb_uint32;
243 }
244
245 }
246 fr_pair_append(&child->request_pairs, vp);
247
248 if ((gext->src) && (tmpl_copy_pair_children(child->request_ctx, &child->request_pairs, request, gext->src) < -1)) {
249 RPEDEBUG("Failed copying source attributes into subrequest");
250 goto fail;
251 }
252
253 /*
254 * Setup the child so it'll inform us when
255 * it resumes, or if it detaches.
256 *
257 * frame->instruction should be consistent
258 * as it's allocated by the unlang compiler.
259 */
260 if (unlang_child_request_init(cr, cr, child, NULL, NULL, frame->instruction, false) < 0) goto fail;
261
262 /*
263 * Push the first instruction the child's
264 * going to run.
265 */
266 if (unlang_interpret_push(child, g->children, frame->result,
267 UNLANG_NEXT_SIBLING, UNLANG_SUB_FRAME) < 0) goto fail;
268
269 /*
270 * Finally, setup the function that will be
271 * called when the child indicates the
272 * parent should be resumed.
273 */
275
276 /*
277 * This is a common function, either pushed
278 * onto the parent's stack, or called directly
279 * from the subrequest instruction..
280 */
281 return unlang_subrequest_child_run(p_result, request, frame); /* returns UNLANG_ACTION_YIELD */
282}
283
284/** Free a child request, detaching it from its parent and freeing allocated memory
285 *
286 * @param[in] child to free.
287 */
289{
290 request_detach(*child);
291 talloc_free(*child);
292 *child = NULL;
293}
294
295/** Allocate a subrequest to run through a virtual server at some point in the future
296 *
297 * @param[in] parent to hang sub request off of.
298 * @param[in] namespace the child will operate in.
299 * @return
300 * - A new child request.
301 * - NULL on failure.
302 */
307
308
309/** Function to run in the context of the parent on resumption
310 *
311 * @note Only executes if unlang_subrequest_child_push was called, not with the normal subrequest keyword.
312 */
315{
316 unlang_child_request_t *cr = talloc_get_type_abort(frame->state, unlang_child_request_t);
317
318 if (cr->result.rcode == RLM_MODULE_NOT_SET) {
319 *p_result = cr->result.rcode = RLM_MODULE_NOOP;
320 }
321
322 if (cr->result.p_result) *cr->result.p_result = cr->result.rcode;
323 cr->result.priority = frame->priority;
324
325 /*
326 * We can free the child here as we're its parent
327 */
328 if (cr->config.free_child) {
331 } else {
332 TALLOC_FREE(cr->request);
333 }
334 }
335
337}
338
339/** Function called by the unlang interpreter, or manually to start the child running
340 *
341 * The reason why we do this on the unlang stack is so that _this_ frame
342 * is marked as resumable in the parent, not whatever frame was previously
343 * being processed by the interpreter when the parent was called.
344 *
345 * i.e. after calling unlang_subrequest_child_push, the code in the parent
346 * can call UNLANG_ACTION_PUSHED_CHILD, which will result in _this_ frame
347 * being executed, and _this_ frame can yield.
348 *
349 * @note Called from the parent to start a child running.
350 */
353{
354 unlang_child_request_t *cr = talloc_get_type_abort(frame->state, unlang_child_request_t);
355 request_t *child = cr->request;
356
357 /*
358 * No parent means this is a pre-detached child
359 * so the parent should continue executing.
360 */
361 if (!child || !child->parent) return UNLANG_ACTION_CALCULATE_RESULT;
362
363
364 /*
365 * Ensure we restore the session state information
366 * into the child.
367 */
368 if (cr->config.session_unique_ptr) fr_state_restore_to_child(child,
369 cr->config.session_unique_ptr,
370 cr->num);
371 /*
372 * Ensures the child is setup correctly and adds
373 * it into the runnable queue of whatever owns
374 * the interpreter.
375 */
377
378 /*
379 * This function is being called by something
380 * other than the subrequest keyword.
381 *
382 * Set a different resumption function that
383 * just writes the final rcode out.
384 */
385 if (frame->process == unlang_subrequest_child_run) {
387 }
388
389 cr->state = CHILD_RUNNABLE;
390
391 return UNLANG_ACTION_YIELD;
392}
393
394/** Push a pre-existing child back onto the stack as a subrequest
395 *
396 * The child *MUST* have been allocated with unlang_io_subrequest_alloc, or something
397 * that calls it.
398 *
399 * After the child is no longer required it *MUST* be freed with #unlang_subrequest_detach_and_free.
400 * It's not enough to free it with talloc_free.
401 *
402 * This function should be called _before_ pushing any additional frames onto the child's
403 * stack for it to execute.
404 *
405 * The parent should return UNLANG_ACTION_PUSHED_CHILD, when it's done setting up the
406 * child request. It should NOT return UNLANG_ACTION_YIELD.
407 *
408 * @param[in] p_result Where to write the result of the subrequest.
409 * @param[in] child to push.
410 * @param[in] unique_session_ptr Unique identifier for child's session data.
411 * @param[in] free_child automatically free the child when it's finished executing.
412 * This is useful if extracting the result from the child is
413 * done using the child's stack, and so the parent never needs
414 * to access it.
415 * @param[in] top_frame Set to UNLANG_TOP_FRAME if the interpreter should return.
416 * Set to UNLANG_SUB_FRAME if the interprer should continue.
417 * @return
418 * - 0 on success.
419 * - -1 on failure.
420 */
421
423 rlm_rcode_t *p_result, void const *unique_session_ptr, bool free_child, bool top_frame)
424{
427
428 static unlang_t subrequest_instruction = {
430 .name = "subrequest",
431 .debug_name = "subrequest",
432 .actions = {
433 .actions = {
434 [RLM_MODULE_REJECT] = 0,
435 [RLM_MODULE_FAIL] = 0,
436 [RLM_MODULE_OK] = 0,
437 [RLM_MODULE_HANDLED] = 0,
438 [RLM_MODULE_INVALID] = 0,
441 [RLM_MODULE_NOOP] = 0,
443 },
444 .retry = RETRY_INIT,
445 }
446 };
447
448 fr_assert_msg(free_child || child->parent, "Child's request pointer must not be NULL when calling subrequest_child_push");
449
451 "Child stack depth must be 0 (not %d), when calling subrequest_child_push",
452 stack_depth_current(child))) return -1;
453
454 /*
455 * Push a new subrequest frame onto the stack
456 * of the parent.
457 *
458 * This allocates memory for the frame state
459 * which we fill in below.
460 *
461 * This frame executes once the subrequest has
462 * completed.
463 */
464 if (unlang_interpret_push(child->parent, &subrequest_instruction,
465 RLM_MODULE_NOT_SET, UNLANG_NEXT_STOP, top_frame) < 0) {
466 return -1;
467 }
468
469 frame = frame_current(child->parent);
471
472 /*
473 * Setup the state for the subrequest
474 */
475 cr = talloc_get_type_abort(frame_current(child->parent)->state, unlang_child_request_t);
476
477 /*
478 * Initialise our frame state, and push the first
479 * instruction onto the child's stack.
480 *
481 * This instruction will mark the parent as runnable
482 * when it executed.
483 */
484 if (unlang_child_request_init(cr, cr, child, p_result, NULL, unique_session_ptr, free_child) < 0) return -1;
485
486 return 0;
487}
488
489/** Add a child request to the runnable queue
490 *
491 * @param[in] request to add to the runnable queue.
492 * @return
493 * - 0 on success.
494 * - -1 on failure.
495 */
497{
498 /*
499 * Ensures the child is setup correctly and adds
500 * it into the runnable queue of whatever owns
501 * the interpreter.
502 */
503 interpret_child_init(request);
504
505 if (request_detach(request) < 0) {
506 RPEDEBUG("Failed detaching request");
507 return -1;
508 }
509
510 return 0;
511}
512
513/** Initialise subrequest ops
514 *
515 */
517{
519 &(unlang_op_t){
520 .name = "subrequest",
521 .interpret = unlang_subrequest_init,
522 .signal = unlang_subrequest_signal,
523 /*
524 * Frame can't be cancelled, because children need to
525 * write out status to the parent. If we don't do this,
526 * then all children must be detachable and must detach
527 * so they don't try and write out status to a "done"
528 * parent.
529 *
530 * It's easier to allow the child/parent relationship
531 * to end normally so that non-detachable requests are
532 * guaranteed the parent still exists.
533 */
535 .frame_state_size = sizeof(unlang_child_request_t),
536 .frame_state_type = "unlang_child_request_t",
537 });
538
539 if (unlang_child_request_op_init() < 0) return -1;
540
541 return 0;
542}
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_EXECUTE_NEXT
Execute the next unlang_t.
Definition action.h:38
@ 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:41
#define RCSID(id)
Definition build.h:485
#define UNUSED
Definition build.h:317
int unlang_child_request_op_init(void)
int unlang_child_request_init(TALLOC_CTX *ctx, unlang_child_request_t *out, request_t *child, rlm_rcode_t *p_result, unsigned int *sibling_count, void const *unique_session_ptr, bool free_child)
Initialize a child request.
struct unlang_child_request_t::@100 config
request_t * request
Child request. The actual request the child will run.
struct unlang_child_request_t::@101 result
unlang_child_request_state_t state
State of the child.
@ CHILD_RUNNABLE
Running/runnable.
@ CHILD_DETACHED
Child has detached, we can't signal it or communicate with it anymore.
@ CHILD_CANCELLED
Child was cancelled.
int num
The child number.
Each child has a state, a number, a request, and a count of their siblings.
fr_table_num_sorted_t const mod_rcode_table[]
Definition compile.c:78
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:210
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:156
#define MEM(x)
Definition debug.h:36
fr_value_box_t const * value
Enum value (what name maps to).
Definition dict.h:236
fr_dict_enum_value_t const * fr_dict_enum_by_value(fr_dict_attr_t const *da, fr_value_box_t const *value)
Lookup the structure representing an enum value in a fr_dict_attr_t.
Definition dict_util.c:3393
fr_dict_enum_value_t const * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition dict_util.c:3439
Value of an enumerated attribute.
Definition dict.h:232
bool unlang_request_is_done(request_t const *request)
Return whether a request has been marked done.
Definition interpret.c:1330
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:143
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
Definition interpret.c:1147
#define UNLANG_SUB_FRAME
Definition interpret.h:36
Private declarations for the unlang interpreter.
static void interpret_child_init(request_t *request)
#define RDEBUG3(fmt,...)
Definition log.h:343
#define RPDEBUG(fmt,...)
Definition log.h:346
#define RPEDEBUG(fmt,...)
Definition log.h:376
void unlang_register(int type, unlang_op_t *op)
Register an operation with the interpreter.
Definition base.c:63
request_t * unlang_io_subrequest_alloc(request_t *parent, fr_dict_t const *namespace, bool detachable)
Allocate a child request based on the parent.
Definition io.c:39
talloc_free(reap)
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
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:2329
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:1351
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition pair.c:287
#define fr_assert(_expr)
Definition rad_assert.h:38
#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:52
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition rcode.h:48
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition rcode.h:44
int request_detach(request_t *child)
Unlink a subrequest from its parent.
Definition request.c:542
#define request_is_detachable(_x)
Definition request.h:187
void fr_state_restore_to_child(request_t *child, void const *unique_ptr, int unique_int)
Restore subrequest data from a parent request.
Definition state.c:857
int tmpl_find_vp(fr_pair_t **out, request_t *request, tmpl_t const *vpt))
Returns the first VP matching a tmpl_t.
Definition tmpl_eval.c:768
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition tmpl.h:801
int tmpl_copy_pair_children(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, tmpl_t const *vpt))
Copy children of pairs matching a tmpl_t in the current request_t.
Definition tmpl_eval.c:720
fr_signal_t
Signals that can be generated/processed by request signal handlers.
Definition signal.h:38
@ FR_SIGNAL_DETACH
Request is being detached from its parent.
Definition signal.h:45
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
static unlang_action_t unlang_subrequest_parent_resume(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Parent being resumed after a child completes.
Definition subrequest.c:97
int unlang_subrequest_child_push(request_t *child, rlm_rcode_t *p_result, void const *unique_session_ptr, bool free_child, bool top_frame)
Push a pre-existing child back onto the stack as a subrequest.
Definition subrequest.c:422
static unlang_action_t unlang_subrequest_child_done(rlm_rcode_t *p_result, UNUSED request_t *request, unlang_stack_frame_t *frame)
Function to run in the context of the parent on resumption.
Definition subrequest.c:313
int unlang_subrequest_op_init(void)
Initialise subrequest ops.
Definition subrequest.c:516
static void unlang_subrequest_signal(UNUSED request_t *request, unlang_stack_frame_t *frame, fr_signal_t action)
Send a signal from parent request to subrequest.
Definition subrequest.c:40
int unlang_subrequest_child_push_and_detach(request_t *request)
Add a child request to the runnable queue.
Definition subrequest.c:496
static unlang_action_t unlang_subrequest_init(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Allocates a new subrequest and initialises it.
Definition subrequest.c:166
request_t * unlang_subrequest_alloc(request_t *parent, fr_dict_t const *namespace)
Allocate a subrequest to run through a virtual server at some point in the future.
Definition subrequest.c:303
unlang_action_t unlang_subrequest_child_run(UNUSED rlm_rcode_t *p_result, UNUSED request_t *request, unlang_stack_frame_t *frame)
Function called by the unlang interpreter, or manually to start the child running.
Definition subrequest.c:351
void unlang_subrequest_detach_and_free(request_t **child)
Free a child request, detaching it from its parent and freeing allocated memory.
Definition subrequest.c:288
static unlang_subrequest_t * unlang_group_to_subrequest(unlang_group_t *g)
Cast a group structure to the subrequest keyword extension.
tmpl_t * vpt
Value to expand to find the value to place into the packet-type attribute.
fr_dict_attr_t const * attr_packet_type
Packet-type attribute in the subrequest protocol.
tmpl_t * src
Pairs to copy into the subrequest request list.
fr_dict_t const * dict
Dictionary of the subrequest protocol.
tmpl_t * dst
Where to copy pairs from the reply list in the subrequest to.
fr_dict_enum_value_t const * type_enum
Static enumeration value for attr_packet_type.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:772
fr_pair_t * tmpl_dcursor_pair_build(fr_pair_t *parent, fr_dcursor_t *cursor, fr_dict_attr_t const *da, UNUSED void *uctx)
Simple pair building callback for use with tmpl_dcursors.
void tmpl_dcursor_clear(tmpl_dcursor_ctx_t *cc)
Clear any temporary state allocations.
#define tmpl_dcursor_build_init(_err, _ctx, _cc, _cursor, _request, _vpt, _build, _uctx)
Maintains state between cursor calls.
Private interpreter structures and functions.
#define UNLANG_NORMAL_CHILD
#define UNLANG_DETACHABLE
#define UNLANG_NEXT_SIBLING
Definition unlang_priv.h:98
void * state
Stack frame specialisations.
#define UNLANG_NEXT_STOP
Definition unlang_priv.h:97
int priority
Result priority.
static unlang_group_t * unlang_generic_to_group(unlang_t const *p)
static unlang_stack_frame_t * frame_current(request_t *request)
static int stack_depth_current(request_t *request)
@ UNLANG_TYPE_SUBREQUEST
create a child subrequest
Definition unlang_priv.h:66
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.
unlang_t const * instruction
The unlang node we're evaluating.
rlm_rcode_t result
The result from executing the instruction.
@ UNLANG_OP_FLAG_DEBUG_BRACES
Print debug braces.
@ UNLANG_OP_FLAG_RCODE_SET
Set request->rcode to the result of this operation.
@ UNLANG_OP_FLAG_NO_CANCEL
Must not be cancelled.
unlang_process_t process
function to call for interpreting this stack frame
unlang_type_t type
The specialisation of this node.
unlang_t * children
Children beneath this group.
Generic representation of a grouping.
An unlang operation.
A node in a graph of unlang_op_t (s) that we execute.
Our interpreter stack, as distinct from the C stack.
static fr_slen_t parent
Definition pair.h:845
#define RETRY_INIT
Definition retry.h:39
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
Definition value.c:3574
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
Definition value.h:606