26 RCSIDH(call_env_h,
"$Id: 750c489514607c999a99c7757b277b38dd985872 $")
32 #include <freeradius-devel/util/dlist.h>
41 FR_DLIST_TYPEDEFS(call_env_parsed, call_env_parsed_head_t, call_env_parsed_entry_t)
43 #include <freeradius-devel/util/value.h>
44 #include <freeradius-devel/unlang/action.h>
45 #include <freeradius-devel/server/cf_parse.h>
46 #include <freeradius-devel/server/dl_module.h>
47 #include <freeradius-devel/server/module.h>
48 #include <freeradius-devel/server/request.h>
49 #include <freeradius-devel/server/tmpl.h>
73 typedef enum CC_HINT(flag_enum) {
103 #define call_env_pair_flags(_flags) (((_flags) & (CALL_ENV_FLAG_SUBSECTION)) == 0)
109 #define call_env_subsection_flags(_flags) (((_flags) & (CALL_ENV_FLAG_CONCAT | CALL_ENV_FLAG_SINGLE | CALL_ENV_FLAG_MULTI | CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_FORCE_QUOTE | CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_PARSE_MISSING)) == 0)
111 #define call_env_required(_flags) ((_flags) & CALL_ENV_FLAG_REQUIRED)
113 #define call_env_concat(_flags) ((_flags) & CALL_ENV_FLAG_CONCAT)
115 #define call_env_single(_flags) ((_flags) & CALL_ENV_FLAG_SINGLE)
117 #define call_env_multi(_flags) ((_flags) & CALL_ENV_FLAG_MULTI)
119 #define call_env_nullable(_flags) ((_flags) & CALL_ENV_FLAG_NULLABLE)
121 #define call_env_force_quote(_flags) ((_flags) & CALL_ENV_FLAG_FORCE_QUOTE)
123 #define call_env_parse_only(_flags) ((_flags) & CALL_ENV_FLAG_PARSE_ONLY)
125 #define call_env_attribute(_flags) ((_flags) & CALL_ENV_FLAG_ATTRIBUTE)
127 #define call_env_is_subsection(_flags) ((_flags) & CALL_ENV_FLAG_SUBSECTION)
129 #define call_env_parse_missing(_flags) ((_flags) & CALL_ENV_FLAG_PARSE_MISSING)
131 #define call_env_secret(_flags) ((_flags) & CALL_ENV_FLAG_SECRET)
185 char const *type_name;
231 #define CALL_ENV_TERMINATOR { NULL }
235 #define FR_CALL_ENV_METHOD_OUT(_inst) \
236 .inst_size = sizeof(_inst), \
237 .inst_type = STRINGIFY(_inst) \
254 #define CALL_ENV_PARSE_TYPE(_s, _f) \
255 _Generic((((_s *)NULL)->_f), \
256 tmpl_t const * : CALL_ENV_PARSE_TYPE_TMPL, \
257 tmpl_t * : CALL_ENV_PARSE_TYPE_TMPL, \
258 fr_value_box_t const * : CALL_ENV_PARSE_TYPE_VALUE_BOX, \
259 fr_value_box_t * : CALL_ENV_PARSE_TYPE_VALUE_BOX, \
260 default : CALL_ENV_PARSE_TYPE_VOID \
265 #define FR_CALL_ENV_SINGLE(_s, _f, _c) \
266 _Generic((((_s *)NULL)->_f), \
267 fr_value_box_t : __builtin_choose_expr(_c, CALL_ENV_FLAG_NONE, CALL_ENV_FLAG_SINGLE), \
268 fr_value_box_t * : __builtin_choose_expr(_c, CALL_ENV_FLAG_NONE, CALL_ENV_FLAG_SINGLE), \
269 fr_value_box_list_t : CALL_ENV_FLAG_NONE, \
270 fr_value_box_list_t * : CALL_ENV_FLAG_NONE, \
271 default : CALL_ENV_FLAG_NONE \
276 #define FR_CALL_ENV_MULTI(_s, _f) \
277 _Generic((((_s *)NULL)->_f), \
278 fr_value_box_t : CALL_ENV_FLAG_NONE, \
279 fr_value_box_t * : CALL_ENV_FLAG_MULTI, \
280 fr_value_box_list_t : CALL_ENV_FLAG_NONE, \
281 fr_value_box_list_t * : CALL_ENV_FLAG_MULTI \
286 #define FR_CALL_ENV_CONCAT(_c, _ct) \
287 __builtin_choose_expr(_ct == FR_TYPE_STRING, _c, \
288 __builtin_choose_expr(_ct == FR_TYPE_OCTETS, _c, \
289 __builtin_choose_expr(_c, (void)0, false)))
293 #define FR_CALL_ENV_DST_TYPE(_s, _f) \
294 _Generic((((_s *)NULL)->_f), \
295 fr_value_box_t : CALL_ENV_RESULT_TYPE_VALUE_BOX, \
296 fr_value_box_t * : CALL_ENV_RESULT_TYPE_VALUE_BOX, \
297 fr_value_box_list_t : CALL_ENV_RESULT_TYPE_VALUE_BOX_LIST, \
298 fr_value_box_list_t * : CALL_ENV_RESULT_TYPE_VALUE_BOX_LIST \
301 #define FR_CALL_ENV_DST_SIZE(_s, _f) \
302 _Generic((((_s *)NULL)->_f), \
303 fr_value_box_t : sizeof(fr_value_box_t), \
304 fr_value_box_t * : sizeof(fr_value_box_t), \
305 fr_value_box_list_t : sizeof(fr_value_box_list_t), \
306 fr_value_box_list_t * : sizeof(fr_value_box_list_t), \
310 #define FR_CALL_ENV_RESULT_TYPE_NAME(_s, _f) \
311 _Generic((((_s *)NULL)->_f), \
312 fr_value_box_t : "fr_value_box_t", \
313 fr_value_box_t * : "fr_value_box_t", \
314 fr_value_box_list_t : "fr_value_box_list_t", \
315 fr_value_box_list_t * : "fr_value_box_list_t", \
321 #define CALL_ENV_FLAGS(_cast_type, _flags, _struct, _field) \
322 (FR_CALL_ENV_CONCAT(((_flags) & CALL_ENV_FLAG_CONCAT), _cast_type) | \
323 FR_CALL_ENV_SINGLE(_struct, _field, ((_flags) & CALL_ENV_FLAG_CONCAT)) | \
324 FR_CALL_ENV_MULTI(_struct, _field) |\
325 ((_flags) & ~CALL_ENV_FLAG_CONCAT)) \
335 #define FR_CALL_ENV_OFFSET(_name, _cast_type, _flags, _struct, _field) \
337 .flags = CALL_ENV_FLAGS(_cast_type, _flags, _struct, _field), \
339 .cast_type = _cast_type, \
340 .type = FR_CALL_ENV_DST_TYPE(_struct, _field), \
341 .size = FR_CALL_ENV_DST_SIZE(_struct, _field), \
342 .type_name = FR_CALL_ENV_RESULT_TYPE_NAME(_struct, _field), \
343 .offset = offsetof(_struct, _field), \
346 .type = CALL_ENV_PARSE_TYPE_TMPL \
360 #define FR_CALL_ENV_PARSE_OFFSET(_name, _cast_type, _flags, _struct, _field, _parse_field) \
362 .flags = CALL_ENV_FLAGS(_cast_type, _flags, _struct, _field), \
364 .cast_type = _cast_type, \
365 .type = FR_CALL_ENV_DST_TYPE(_struct, _field), \
366 .size = FR_CALL_ENV_DST_SIZE(_struct, _field), \
367 .type_name = FR_CALL_ENV_RESULT_TYPE_NAME(_struct, _field), \
368 .offset = offsetof(_struct, _field), \
370 .offset = offsetof(_struct, _parse_field), \
371 .type = CALL_ENV_PARSE_TYPE(_struct, _parse_field) \
384 #define FR_CALL_ENV_PARSE_ONLY_OFFSET(_name, _cast_type, _flags, _struct, _parse_field) \
386 .flags = (_flags) | CALL_ENV_FLAG_PARSE_ONLY, \
388 .cast_type = _cast_type, \
390 .offset = offsetof(_struct, _parse_field), \
391 .type = CALL_ENV_PARSE_TYPE(_struct, _parse_field) \
397 #define FR_CALL_ENV_SUBSECTION(_name, _name2, _flags, _subcs ) \
399 .flags = CALL_ENV_FLAG_SUBSECTION | (_flags), \
407 #define FR_CALL_ENV_SUBSECTION_FUNC(_name, _name2, _flags, _func) \
409 .flags = CALL_ENV_FLAG_SUBSECTION | (_flags), \
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
call_env_flags_t flags
Flags controlling parser behaviour.
int(* call_env_parse_section_t)(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_ctx_t const *cec, call_env_parser_t const *rule)
Callback for performing custom parsing of a CONF_SECTION.
call_env_ctx_type_t type
Type of callenv ctx.
@ CALL_ENV_CTX_TYPE_XLAT
The callenv is registered to an xlat.
@ CALL_ENV_CTX_TYPE_MODULE
The callenv is registered to a module method.
void call_env_parsed_free(call_env_parsed_head_t *parsed, call_env_parsed_t *ptr)
Remove a call_env_parsed_t from the list of parsed call envs.
char const * name
Of conf pair to pass to tmpl_tokenizer.
unlang_action_t call_env_expand(TALLOC_CTX *ctx, request_t *request, call_env_result_t *result, void **env_data, call_env_t const *call_env)
Initialise the expansion of a call environment.
call_env_result_type_t
What type of structure is produced by the evaluation phase.
@ CALL_ENV_RESULT_TYPE_VALUE_BOX_LIST
Output of the evaluation phase is a list of value boxes.
@ CALL_ENV_RESULT_TYPE_VALUE_BOX
Output of the evaluation phase is a single value box.
size_t inst_size
Size of per call env.
call_env_parsed_t * call_env_parsed_add(TALLOC_CTX *ctx, call_env_parsed_head_t *head, call_env_parser_t const *rule)
Allocate a new call_env_parsed_t structure and add it to the list of parsed call envs.
call_env_parser_t const * env
Parsing rules for call method env.
section_name_t const * asked
The actual name1/name2 that resolved to a module_method_binding_t.
void const * uctx
User context for callback functions.
void call_env_parsed_set_multi_index(call_env_parsed_t *parsed, size_t count, size_t index)
Assign a count and index to a call_env_parsed_t.
char const * inst_type
Type of per call env.
void _mismatch_flags
Dummy type used to indicate bad flags.
@ CALL_ENV_FLAG_CONCAT
If the tmpl produced multiple boxes they should be concatenated.
@ CALL_ENV_FLAG_SUBSECTION
This is a subsection.
@ CALL_ENV_FLAG_SINGLE
If the tmpl produces more than one box this is an error.
@ CALL_ENV_FLAG_ATTRIBUTE
Tmpl must contain an attribute reference.
@ CALL_ENV_FLAG_FORCE_QUOTE
Force quote method when parsing tmpl.
@ CALL_ENV_FLAG_PARSE_ONLY
The result of parsing will not be evaluated at runtime.
@ CALL_ENV_FLAG_SECRET
The value is a secret, and should not be logged.
@ CALL_ENV_FLAG_MULTI
Multiple instances of the conf pairs are allowed.
@ CALL_ENV_FLAG_REQUIRED
Associated conf pair or section is required.
@ CALL_ENV_FLAG_PARSE_MISSING
If this subsection is missing, still parse it.
@ CALL_ENV_FLAG_NULLABLE
Tmpl expansions are allowed to produce no output.
call_env_t * call_env_alloc(TALLOC_CTX *ctx, char const *name, call_env_method_t const *call_env_method, tmpl_rules_t const *rules, CONF_SECTION *cs, call_env_ctx_t const *cec))
Given a call_env_method, parse all call_env_pair_t in the context of a specific call to an xlat or mo...
void call_env_parsed_set_data(call_env_parsed_t *parsed, void const *data)
Assign data to a call_env_parsed_t.
call_env_parsed_head_t parsed
The per call parsed call environment.
call_env_parse_type_t
What type of structure is produced by the parsing phase.
@ CALL_ENV_PARSE_TYPE_VALUE_BOX
Output of the parsing phase is a single value box (static data).
@ CALL_ENV_PARSE_TYPE_TMPL
Output of the parsing phase is a tmpl_t.
@ CALL_ENV_PARSE_TYPE_VOID
Output of the parsing phase is undefined (a custom structure).
void call_env_parsed_set_value(call_env_parsed_t *parsed, fr_value_box_t const *vb)
Assign a value box to a call_env_parsed_t.
module_instance_t const * mi
Module instance that the callenv is registered to.
int call_env_parse_pair(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_ctx_t const *cec, call_env_parser_t const *rule)
call_env_method_t const * method
The method this call env is for.
int(* call_env_parse_pair_t)(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_ctx_t const *cec, call_env_parser_t const *rule)
Callback for performing custom parsing of a CONF_PAIR.
void call_env_parsed_set_tmpl(call_env_parsed_t *parsed, tmpl_t const *tmpl)
Assign a tmpl to a call_env_parsed_t.
Structure containing both a talloc pool, a list of parsed call_env_pairs.
Common header for all CONF_* types.
A section grouping multiple CONF_PAIR.
#define FR_DLIST_TYPES(_name)
Define type specific wrapper structs for dlists.
#define FR_DLIST_TYPEDEFS(_name, _head, _entry)
Define friendly names for type specific dlist head and entry structures.
Optional arguments passed to vp_tmpl functions.
fr_aka_sim_id_type_t type
Escaping rules for tmpls.
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
static size_t char ** out