The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
map.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: 451180effff56044b5011a657f9105526b2b55ea $
19 *
20 * @brief map and unlang integration.
21 * @brief Unlang "map" keyword evaluation.
22 *
23 * @ingroup AVP
24 *
25 * @copyright 2018 The FreeRADIUS server project
26 * @copyright 2018 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
27 */
28RCSID("$Id: 451180effff56044b5011a657f9105526b2b55ea $")
29
30#include <freeradius-devel/server/base.h>
31#include <freeradius-devel/unlang/tmpl.h>
32#include <freeradius-devel/unlang/map.h>
33
34#include "map_priv.h"
35
36/** State of a map block
37 *
38 */
39typedef struct {
40 fr_value_box_list_t src_result; //!< Result of expanding the map source.
41
42 /** @name Resumption and signalling
43 * @{
44 */
45 void *rctx; //!< for resume / signal
46 map_proc_func_t resume; //!< resumption handler
47 unlang_map_signal_t signal; //!< for signal handlers
48 fr_signal_t sigmask; //!< Signals to block.
49
50 /** @} */
52
53/** Wrapper to create a map_ctx_t as a compound literal
54 *
55 * @param[in] _mod_inst of the module being called.
56 * @param[in] _map_inst of the map being called.
57 * @param[in] _rctx Resume ctx (if any).
58 */
59#define MAP_CTX(_mod_inst, _map_inst, _rctx) &(map_ctx_t){ .moi = _mod_inst, .mpi = _map_inst, .rctx = _rctx }
60
62#ifdef WITH_VERIFY_PTR
64#else
66#endif
67 )
68{
69 unlang_frame_state_map_proc_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_map_proc_t);
70 unlang_frame_state_map_proc_t *map_proc_state = talloc_get_type_abort(frame->state, unlang_frame_state_map_proc_t);
71 map_proc_func_t resume;
72 unlang_group_t *g = unlang_generic_to_group(frame->instruction);
76
77#ifdef WITH_VERIFY_PTR
78 VALUE_BOX_LIST_VERIFY(&map_proc_state->src_result);
79#endif
80 resume = state->resume;
81 state->resume = NULL;
82
83 /*
84 * Call any map resume function
85 */
86 if (resume) ua = resume(p_result, MAP_CTX(inst->proc->mod_inst, inst->data, state->rctx),
87 request, &map_proc_state->src_result, inst->maps);
88 return ua;
89}
90
91/** Yield a request back to the interpreter from within a module
92 *
93 * This passes control of the request back to the unlang interpreter, setting
94 * callbacks to execute when the request is 'signalled' asynchronously, or whatever
95 * timer or I/O event the module was waiting for occurs.
96 *
97 * @note The module function which calls #unlang_module_yield should return control
98 * of the C stack to the unlang interpreter immediately after calling #unlang_module_yield.
99 * A common pattern is to use ``return unlang_module_yield(...)``.
100 *
101 * @param[in] request The current request.
102 * @param[in] resume Called on unlang_interpret_mark_runnable().
103 * @param[in] signal Called on unlang_action().
104 * @param[in] sigmask Set of signals to block.
105 * @param[in] rctx to pass to the callbacks.
106 * @return
107 * - UNLANG_ACTION_YIELD.
108 */
110 map_proc_func_t resume, unlang_map_signal_t signal, fr_signal_t sigmask, void *rctx)
111{
112 unlang_stack_t *stack = request->stack;
113 unlang_stack_frame_t *frame = &stack->frame[stack->depth];
114 unlang_frame_state_map_proc_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_map_proc_t);
115
116 REQUEST_VERIFY(request); /* Check the yielded request is sane */
117
118 state->rctx = rctx;
119 state->resume = resume;
120 state->signal = signal;
121 state->sigmask = sigmask;
122
123 /*
124 * We set the repeatable flag here,
125 * so that the resume function is always
126 * called going back up the stack.
127 */
129
130 return UNLANG_ACTION_YIELD;
131}
132
134{
137
139 unlang_frame_state_map_proc_t *map_proc_state = talloc_get_type_abort(frame->state, unlang_frame_state_map_proc_t);
140
141 RDEBUG2("MAP %s \"%pM\"", inst->proc->name, &map_proc_state->src_result);
142
143 VALUE_BOX_LIST_VERIFY(&map_proc_state->src_result);
145
146 return inst->proc->evaluate(p_result, MAP_CTX(inst->proc->mod_inst, inst->data, NULL),
147 request, &map_proc_state->src_result, inst->maps);
148}
149
151{
155 unlang_frame_state_map_proc_t *map_proc_state = talloc_get_type_abort(frame->state, unlang_frame_state_map_proc_t);
156
157 /*
158 * Initialise the frame state
159 */
160 repeatable_set(frame);
161
162 fr_value_box_list_init(&map_proc_state->src_result);
163 /*
164 * Set this BEFORE doing anything else, as we will be
165 * called again after unlang_xlat_push() returns.
166 */
167 frame->process = map_proc_apply;
168
169 /*
170 * Expand the map source
171 */
172 if (inst->src) switch (inst->src->type) {
173 default:
174 {
175 fr_value_box_t *src_result = NULL;
176 if (tmpl_aexpand(frame->state, &src_result,
177 request, inst->src, NULL, NULL) < 0) {
178 REDEBUG("Failed expanding map src");
179 error:
181 }
182 fr_value_box_list_insert_head(&map_proc_state->src_result, src_result);
183 break;
184 }
185 case TMPL_TYPE_EXEC:
186 if (unlang_tmpl_push(map_proc_state, NULL, &map_proc_state->src_result,
187 request, inst->src, NULL, UNLANG_SUB_FRAME) < 0) {
189 }
191
192 case TMPL_TYPE_XLAT:
193 if (unlang_xlat_push(map_proc_state, NULL, &map_proc_state->src_result,
194 request, tmpl_xlat(inst->src), false) < 0) {
196 }
198
199
200 case TMPL_TYPE_REGEX:
205 fr_assert(0);
206 goto error;
207 }
208
209 return map_proc_apply(p_result, request, frame);
210}
211
213{
215
216 /*
217 * map <module-name> <arg>
218 */
219 if (gext->vpt) {
220 char quote;
221 size_t quoted_len;
222 char *quoted_str;
223
224 switch (cf_section_argv_quote(g->cs, 0)) {
226 quote = '"';
227 break;
228
230 quote = '\'';
231 break;
232
234 quote = '`';
235 break;
236
237 default:
238 quote = '\0';
239 break;
240 }
241
242 quoted_len = fr_snprint_len(gext->vpt->name, gext->vpt->len, quote);
243 quoted_str = talloc_array(g, char, quoted_len);
244 fr_snprint(quoted_str, quoted_len, gext->vpt->name, gext->vpt->len, quote);
245
246 g->self.name = talloc_typed_asprintf(g, "map %s %s", cf_section_name2(g->cs), quoted_str);
247 g->self.debug_name = g->self.name;
248 talloc_free(quoted_str);
249
250 return 0;
251 }
252
253 g->self.name = talloc_typed_asprintf(g, "map %s", cf_section_name2(g->cs));
254 g->self.debug_name = g->self.name;
255
256 return 0;
257}
258
259/** Validate and fixup a map that's part of an map section.
260 *
261 * @param map to validate.
262 * @param ctx data to pass to fixup function (currently unused).
263 * @return 0 if valid else -1.
264 */
265static int fixup_map_cb(map_t *map, UNUSED void *ctx)
266{
267 switch (map->lhs->type) {
268 case TMPL_TYPE_ATTR:
270 case TMPL_TYPE_XLAT:
271 break;
272
273 default:
274 cf_log_err(map->ci, "Left side of map must be an attribute "
275 "or an xlat (that expands to an attribute), not a %s",
276 tmpl_type_to_str(map->lhs->type));
277 return -1;
278 }
279
280 switch (map->rhs->type) {
283 case TMPL_TYPE_DATA:
284 case TMPL_TYPE_XLAT:
285 case TMPL_TYPE_ATTR:
286 case TMPL_TYPE_EXEC:
287 break;
288
289 default:
290 cf_log_err(map->ci, "Right side of map must be an attribute, literal, xlat or exec, got type %s",
291 tmpl_type_to_str(map->rhs->type));
292 return -1;
293 }
294
295 if (!fr_assignment_op[map->op] && !fr_comparison_op[map->op]) {
296 cf_log_err(map->ci, "Invalid operator \"%s\" in map section. "
297 "Only assignment or filter operators are allowed",
298 fr_table_str_by_value(fr_tokens_table, map->op, "<INVALID>"));
299 return -1;
300 }
301
302 return 0;
303}
304
306{
308 int rcode;
309
311 unlang_map_t *gext;
312
313 unlang_t *c;
314 CONF_SECTION *modules;
315 char const *tmpl_str;
316
317 tmpl_t *vpt = NULL;
318
319 map_proc_t *proc;
320 map_proc_inst_t *proc_inst;
321
322 char const *name2 = cf_section_name2(cs);
323
324 tmpl_rules_t t_rules;
325
326 /*
327 * The RHS is NOT resolved in the context of the LHS.
328 */
329 t_rules = *(unlang_ctx->rules);
330 t_rules.attr.disallow_rhs_resolve = true;
331 RULES_VERIFY(&t_rules);
332
333 modules = cf_section_find(cf_root(cs), "modules", NULL);
334 if (!modules) {
335 cf_log_err(cs, "'map' sections require a 'modules' section");
336 return NULL;
337 }
338
339 proc = map_proc_find(name2);
340 if (!proc) {
341 cf_log_err(cs, "Failed to find map processor '%s'", name2);
342 return NULL;
343 }
345
347 if (!g) return NULL;
348
349 gext = unlang_group_to_map(g);
350
351 /*
352 * If there's a third string, it's the map src.
353 *
354 * Convert it into a template.
355 */
356 tmpl_str = cf_section_argv(cs, 0); /* AFTER name1, name2 */
357 if (tmpl_str) {
359
361
362 /*
363 * Try to parse the template.
364 */
365 (void) tmpl_afrom_substr(gext, &vpt,
366 &FR_SBUFF_IN(tmpl_str, talloc_strlen(tmpl_str)),
367 type,
368 NULL,
369 &t_rules);
370 if (!vpt) {
371 cf_log_perr(cs, "Failed parsing map");
372 error:
373 talloc_free(g);
374 return NULL;
375 }
376
377 /*
378 * Limit the allowed template types.
379 */
380 switch (vpt->type) {
382 case TMPL_TYPE_ATTR:
384 case TMPL_TYPE_XLAT:
386 case TMPL_TYPE_EXEC:
388 case TMPL_TYPE_DATA:
389 break;
390
391 default:
393 cf_log_err(cs, "Invalid third argument for map");
394 return NULL;
395 }
396 }
397
398 /*
399 * This looks at cs->name2 to determine which list to update
400 */
401 map_list_init(&gext->map);
402 rcode = map_afrom_cs(gext, &gext->map, cs, unlang_ctx->rules, &t_rules, fixup_map_cb, NULL, 256);
403 if (rcode < 0) return NULL; /* message already printed */
404 if (map_list_empty(&gext->map)) {
405 cf_log_err(cs, "'map' sections cannot be empty");
406 goto error;
407 }
408
409
410 /*
411 * Call the map's instantiation function to validate
412 * the map and perform any caching required.
413 */
414 proc_inst = map_proc_instantiate(gext, proc, cs, vpt, &gext->map);
415 if (!proc_inst) {
416 cf_log_err(cs, "Failed instantiating map function '%s'", name2);
417 goto error;
418 }
420
421 gext->vpt = vpt;
422 gext->proc_inst = proc_inst;
423
425
426 /*
427 * Cache the module in the unlang_group_t struct.
428 *
429 * Ensure that the module has a "map" entry in its module
430 * header? Or ensure that the map is registered in the
431 * "bootstrap" phase, so that it's always available here.
432 */
433 if (!pass2_fixup_map_rhs(g, unlang_ctx->rules)) goto error;
434
435 return c;
436}
437
438
440{
442 .name = "map",
443 .type = UNLANG_TYPE_MAP,
445
446 .compile = unlang_compile_map,
447 .interpret = unlang_map_state_init,
448
449 .unlang_size = sizeof(unlang_map_t),
450 .unlang_name = "unlang_map_t",
451
452 .frame_state_size = sizeof(unlang_frame_state_map_proc_t),
453 .frame_state_type = "unlang_frame_state_map_proc_t",
454 });
455}
#define RETURN_UNLANG_ACTION_FATAL
Definition action.h:44
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_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:506
#define UNUSED
Definition build.h:336
#define RULES_VERIFY(_cs, _rules)
Definition cf_file.c:175
Common header for all CONF_* types.
Definition cf_priv.h:49
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
fr_token_t cf_section_argv_quote(CONF_SECTION const *cs, int argc)
Return the quoting for one of the variadic arguments.
Definition cf_util.c:1247
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1184
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1027
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:683
char const * cf_section_argv(CONF_SECTION const *cs, int argc)
Return variadic argument at the specified index.
Definition cf_util.c:1212
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:285
#define cf_root(_cf)
Definition cf_util.h:95
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:292
bool pass2_fixup_map_rhs(unlang_group_t *g, tmpl_rules_t const *rules)
Definition compile.c:213
unlang_group_t * unlang_group_allocate(unlang_t *parent, CONF_SECTION *cs, unlang_type_t type)
Definition compile.c:458
talloc_free(hp)
#define UNLANG_SUB_FRAME
Definition interpret.h:37
int map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, CONF_SECTION *cs, tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules, map_validate_t validate, void *uctx, unsigned int max)
Convert a config section into an attribute map.
Definition map.c:1136
static TALLOC_CTX * unlang_ctx
Definition base.c:71
void unlang_register(unlang_op_t *op)
Register an operation with the interpreter.
Definition base.c:56
map_proc_func_t resume
resumption handler
Definition map.c:46
unlang_action_t unlang_map_yield(request_t *request, map_proc_func_t resume, unlang_map_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
Definition map.c:109
static int fixup_map_cb(map_t *map, UNUSED void *ctx)
Validate and fixup a map that's part of an map section.
Definition map.c:265
static unlang_t * unlang_compile_map(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_ITEM const *ci)
Definition map.c:305
fr_signal_t sigmask
Signals to block.
Definition map.c:48
static int compile_map_name(unlang_group_t *g)
Definition map.c:212
void unlang_map_init(void)
Definition map.c:439
static unlang_action_t map_proc_resume(unlang_result_t *p_result, request_t *request, UNUSED unlang_stack_frame_t *frame)
Definition map.c:61
void * rctx
for resume / signal
Definition map.c:45
static unlang_action_t map_proc_apply(unlang_result_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Definition map.c:133
static unlang_action_t unlang_map_state_init(unlang_result_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Definition map.c:150
unlang_map_signal_t signal
for signal handlers
Definition map.c:47
#define MAP_CTX(_mod_inst, _map_inst, _rctx)
Wrapper to create a map_ctx_t as a compound literal.
Definition map.c:59
fr_value_box_list_t src_result
Result of expanding the map source.
Definition map.c:40
map and unlang integration.
Definition map.c:39
static char * stack[MAX_STACK]
Definition radmin.c:158
map_proc_inst_t * proc_inst
Definition map_priv.h:35
static unlang_map_t * unlang_group_to_map(unlang_group_t *g)
Cast a group structure to the map keyword extension.
Definition map_priv.h:41
map_list_t map
Head of the map list.
Definition map_priv.h:34
tmpl_t * vpt
Definition map_priv.h:33
map_proc_t * map_proc_find(char const *name)
Find a map processor by name.
Definition map_proc.c:80
map_proc_inst_t * map_proc_instantiate(TALLOC_CTX *ctx, map_proc_t const *proc, CONF_SECTION *cs, tmpl_t const *src, map_list_t const *maps)
Create a new map proc instance.
Definition map_proc.c:203
fr_value_box_safe_for_t map_proc_literals_safe_for(map_proc_t const *proc)
Definition map_proc.c:68
unlang_action_t(* map_proc_func_t)(unlang_result_t *p_result, map_ctx_t const *mpctx, request_t *request, fr_value_box_list_t *result, map_list_t const *maps)
Function to evaluate the src string and map the result to server attributes.
Definition map_proc.h:71
Map processor registration.
Map processor instance.
size_t fr_snprint(char *out, size_t outlen, char const *in, ssize_t inlen, char quote)
Escape any non printable or non-UTF8 characters in the input string.
Definition print.c:237
size_t fr_snprint_len(char const *in, ssize_t inlen, char quote)
Find the length of the buffer required to fully escape a string with fr_prints.
Definition print.c:419
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
#define RDEBUG2(fmt,...)
#define RETURN_UNLANG_FAIL
Definition rcode.h:63
#define REQUEST_VERIFY(_x)
Definition request.h:309
#define FR_SBUFF_IN(_start, _len_or_end)
static char const * tmpl_type_to_str(tmpl_type_t type)
Return a static string containing the type name.
Definition tmpl.h:638
fr_value_box_safe_for_t literals_safe_for
safe_for value assigned to literal values in xlats, execs, and data.
Definition tmpl.h:351
#define tmpl_xlat(_tmpl)
Definition tmpl.h:930
@ TMPL_TYPE_REGEX_UNCOMPILED
Regex where compilation is possible but hasn't been performed yet.
Definition tmpl.h:158
@ TMPL_TYPE_ATTR_UNRESOLVED
An attribute reference that we couldn't resolve but looked valid.
Definition tmpl.h:185
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
Definition tmpl.h:142
@ TMPL_TYPE_XLAT
Pre-parsed xlat expansion.
Definition tmpl.h:146
@ TMPL_TYPE_EXEC
Callout to an external script or program.
Definition tmpl.h:150
@ TMPL_TYPE_REGEX_XLAT_UNRESOLVED
A regular expression with unresolved xlat functions or attribute references.
Definition tmpl.h:197
@ TMPL_TYPE_DATA
Value in native boxed format.
Definition tmpl.h:138
@ TMPL_TYPE_REGEX
Compiled (and possibly JIT'd) regular expression.
Definition tmpl.h:154
@ TMPL_TYPE_DATA_UNRESOLVED
Unparsed literal string.
Definition tmpl.h:179
@ TMPL_TYPE_XLAT_UNRESOLVED
A xlat expansion with unresolved xlat functions or attribute references.
Definition tmpl.h:193
@ TMPL_TYPE_REGEX_XLAT
A regex containing xlat expansions.
Definition tmpl.h:162
@ TMPL_TYPE_EXEC_UNRESOLVED
An exec with unresolved xlat function or attribute references.
Definition tmpl.h:189
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
static fr_slen_t vpt
Definition tmpl.h:1269
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:339
#define tmpl_aexpand(_ctx, _out, _request, _vpt, _escape, _escape_ctx)
Expand a tmpl to a C type, allocing a new buffer to hold the string.
Definition tmpl.h:1064
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:336
fr_signal_t
Signals that can be generated/processed by request signal handlers.
Definition signal.h:38
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
eap_type_t type
The preferred EAP-Type of this instance of the EAP-SIM/AKA/AKA' state machine.
Value pair map.
Definition map.h:77
fr_token_t op
The operator that controls insertion of the dst attribute.
Definition map.h:82
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
Definition map.h:78
tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
Definition map.h:79
CONF_ITEM * ci
Config item that the map was created from.
Definition map.h:85
unsigned int disallow_rhs_resolve
map RHS is NOT immediately resolved in the context of the LHS.
Definition tmpl.h:324
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:772
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition talloc.c:545
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition talloc.h:136
int unlang_tmpl_push(TALLOC_CTX *ctx, unlang_result_t *p_result, fr_value_box_list_t *out, request_t *request, tmpl_t const *tmpl, unlang_tmpl_args_t *args, bool top_frame)
Push a tmpl onto the stack for evaluation.
Definition tmpl.c:276
const bool fr_assignment_op[T_TOKEN_LAST]
Definition token.c:170
fr_table_num_ordered_t const fr_tokens_table[]
Definition token.c:33
const bool fr_comparison_op[T_TOKEN_LAST]
Definition token.c:200
enum fr_token fr_token_t
@ T_SINGLE_QUOTED_STRING
Definition token.h:120
@ T_BACK_QUOTED_STRING
Definition token.h:121
@ T_DOUBLE_QUOTED_STRING
Definition token.h:119
void(* unlang_map_signal_t)(map_ctx_t const *mpctx, request_t *request, fr_signal_t action)
A callback when the request gets a fr_signal_t.
Definition map.h:43
int unlang_xlat_push(TALLOC_CTX *ctx, unlang_result_t *p_result, fr_value_box_list_t *out, request_t *request, xlat_exp_head_t const *xlat, bool top_frame)
Push a pre-compiled xlat onto the stack for evaluation.
Definition xlat.c:269
CONF_SECTION * cs
char const * debug_name
Printed in log messages when the node is executed.
void * state
Stack frame specialisations.
static unlang_t * unlang_group_to_generic(unlang_group_t const *p)
static unlang_group_t * unlang_generic_to_group(unlang_t const *p)
char const * name
Unknown...
@ UNLANG_TYPE_MAP
Mapping section (like #UNLANG_TYPE_UPDATE, but uses values from a map_proc_t call).
Definition unlang_priv.h:65
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.
@ UNLANG_OP_FLAG_RCODE_SET
Set request->rcode to the result of this operation.
static void repeatable_set(unlang_stack_frame_t *frame)
unlang_process_t process
function to call for interpreting this stack frame
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.
An unlang stack associated with a request.
static fr_slen_t parent
Definition pair.h:858
#define VALUE_BOX_LIST_VERIFY(_x)
Definition value.h:1371