25RCSID(
"$Id: d1b69681861451a544d195cb3f5d171b2c66c704 $")
27#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
29#include <freeradius-devel/server/virtual_servers.h>
31#include <freeradius-devel/server/cf_file.h>
32#include <freeradius-devel/server/main_config.h>
33#include <freeradius-devel/server/map_proc.h>
34#include <freeradius-devel/server/modpriv.h>
35#include <freeradius-devel/server/module_rlm.h>
38#include <freeradius-devel/unlang/xlat_priv.h>
90#define UPDATE_CTX2 unlang_compile_ctx_copy(&unlang_ctx2, unlang_ctx)
138 cf_log_err(map->
ci,
"Invalid operator \"%s\" in nested map section. "
139 "Only '=' is allowed",
158 if (!map_list_empty(&map->
child)) {
163 cf_log_err(map->
ci,
"Sublists can only be assigned to a known attribute");
172 for (child = map_list_next(&map->
child, NULL);
174 child = map_list_next(&map->
child, child)) {
194 while ((map = map_list_next(&gext->
map, map))) {
227 while ((map = map_list_next(&gext->
map, map))) {
234 if (!gext->
vpt)
return true;
275 while ((map = map_list_next(&gext->
map, map))) {
290 while ((map = map_list_next(&edit->
maps, map))) {
291 if (!map->
rhs)
continue;
359 switch (map->
rhs->type) {
382 cf_log_err(map->
ci,
"Can't copy list into an attribute");
387 cf_log_err(map->
ci,
"Invalid operator \"%s\" in update section. "
388 "Only assignment or filter operators are allowed",
394 cf_log_warn(cp,
"Please use the 'filter' keyword for attribute filtering");
428 cf_log_perr(map->
ci,
"Cannot convert RHS value (%s) to LHS attribute type (%s)",
439 cf_log_err(map->
ci,
"Cannot determine what update action to perform");
502#define T(_x) [T_OP_ ## _x] = true
530 map_t *parent_map = ctx;
533#ifdef STATIC_ANALYZER
534 if (!parent_map)
return -1;
541 cf_log_err(cp,
"Invalid operator '%s' for right-hand side list. It must be a comparison operator",
fr_tokens[map->
op]);
546 cf_log_err(cp,
"Invalid operator '%s' for right-hand side list. It must be '='",
fr_tokens[map->
op]);
557 switch (map->
lhs->type) {
563 cf_log_err(cp,
"Invalid location for %s - it is not a child of %s",
574 cf_log_err(map->
ci,
"Left side of map must be an attribute "
575 "or an xlat (that expands to an attribute), not a %s",
582 switch (map->
rhs->type) {
592 cf_log_err(map->
ci,
"Right side of map must be an attribute, literal, xlat or exec, got type %s",
641 if (!edit)
return NULL;
649 map_list_init(&edit->
maps);
657 map_list_init(&map->
child);
693 !((parent_da->type ==
FR_TYPE_GROUP) && parent_da->flags.internal)) {
694 t_rules.
attr.namespace = parent_da;
705 for (child = map_list_head(&map->
child); child != NULL; child = map_list_next(&map->
child, child)) {
709 cf_log_err(child->
ci,
"Cannot use array references and values when deleting from a list");
717 cf_log_err(child->
ci,
"List deletion must operate directly on the final child");
725 cf_log_err(child->
ci,
"List deletion cannot operate on lists");
739 cf_log_err(cs,
"Cannot use operator '%s' for assigning empty list to '%s' data type.",
755 map_list_insert_tail(&edit->
maps, map);
781 if (!edit)
return NULL;
789 map_list_init(&edit->
maps);
801 if (
map_afrom_cp(edit, &map, map_list_tail(&edit->
maps), cp, &t_rules, NULL,
true) < 0) {
816 cf_log_err(cp,
"Invalid array reference in %s", map->
lhs->name);
822 cf_log_err(cp,
"Cannot delete local variable %s", map->
rhs->name);
838 map_list_insert_tail(&edit->
maps, map);
843#define debug_braces(_type) (unlang_ops[_type].flag & UNLANG_OP_FLAG_DEBUG_BRACES)
854 char const *attr, *
value;
879 cf_log_err(cp,
"Local variables cannot be used here");
912 t_rules->
attr.namespace = NULL;
923 cf_log_err(cp,
"Invalid data type '%s'", attr);
941 char const *attr, *
value;
945 if (!
value)
return 0;
959 else if (strspn(
value,
"0123456789") == strlen(
value)) {
960 if (strlen(
value) > 2) {
962 cf_log_err(cp,
"Priorities MUST be between 1 and 64.");
982 "Unknown module rcode '%s'.",
986 actions->
actions[rcode] = action;
1012 cf_log_err(csi,
"Invalid subsection in 'retry' configuration.");
1023 cf_log_err(csi,
"Retry configuration must specify a value");
1027#define CLAMP(_name, _field, _limit) do { \
1028 if (!fr_time_delta_ispos(actions->retry._field)) { \
1029 cf_log_err(csi, "Invalid value for '" STRINGIFY(_name) " = %s' - value must be positive", \
1033 if (fr_time_delta_cmp(actions->retry._field, fr_time_delta_from_sec(_limit)) > 0) { \
1034 cf_log_err(csi, "Invalid value for '" STRINGIFY(_name) " = %s' - value must be less than " STRINGIFY(_limit) "s", \
1044 if (strcmp(
name,
"initial_rtx_time") == 0) {
1047 cf_log_err(csi,
"Failed parsing '%s = %s' - %s",
1051 CLAMP(initial_rtx_time, irt, 2);
1053 }
else if (strcmp(
name,
"max_rtx_time") == 0) {
1056 CLAMP(max_rtx_time, mrt, 10);
1058 }
else if (strcmp(
name,
"max_rtx_count") == 0) {
1059 unsigned long v = strtoul(
value, 0, 0);
1062 cf_log_err(csi,
"Invalid value for 'max_rtx_count = %s' - value must be between 0 and 10",
1069 }
else if (strcmp(
name,
"max_rtx_duration") == 0) {
1072 CLAMP(max_rtx_duration, mrd, 20);
1075 cf_log_err(csi,
"Invalid item '%s' in 'retry' configuration.",
name);
1086 bool disallow_retry_action =
false;
1113 cf_log_err(csi,
"Invalid subsection. Expected 'action = value'");
1125 if (strcmp(
name,
"retry") == 0) {
1151 cf_log_err(csi,
"initial_rtx_time MUST be non-zero for modules which support retries.");
1156 cf_log_err(csi,
"initial_rtx_time MUST be zero, as only max_rtx_count and max_rtx_duration are used.");
1161 disallow_retry_action =
true;
1173 cf_log_err(csi,
"Cannot use a '%s = retry' action for a module which has its own retries",
1178 if (disallow_retry_action) {
1179 cf_log_err(csi,
"max_rtx_count and max_rtx_duration cannot both be zero when using '%s = retry'",
1187 cf_log_err(csi,
"Cannot use a '%s = retry' action without a 'retry { ... }' section.",
1207 if (!g)
return NULL;
1244 cf_log_err(ci,
"'actions' MUST be the last block in a section");
1249 cf_log_err(ci,
"Invalid name for 'actions' section");
1292 bool was_if =
false;
1293 char const *skip_else = NULL;
1306 t_rules = *unlang_ctx_in->
rules;
1319 char const *
name = NULL;
1348 if (strcmp(
name,
"actions") == 0) {
1356 if ((strcmp(
name,
"else") == 0) || (strcmp(
name,
"elsif") == 0)) {
1362 cf_log_err(ci,
"Invalid location for '%s'. There is no preceding "
1363 "'if' or 'elsif' statement",
name);
1383 "'%s' being always being taken.",
1428 if (!single)
goto fail;
1432 cf_log_err(ci,
"Asked to compile unknown conf type");
1443 switch (single->
type) {
1486 unlang_list_insert_tail(&g->
children, single);
1495 cf_log_warn(ci,
"Skipping remaining instructions due to '%s'",
1512 char const *name1, *name2;
1521 if (!g)
return NULL;
1539 }
else if (!name2) {
1611 if ((strcmp(name1,
"else") == 0) ||
1612 (strcmp(name1,
"elsif") == 0)) {
1613 cf_log_err(ci,
"%s sections cannot contain a \"%s\" statement",
1658 cf_log_err(subcs,
"Unexpected second name in policy");
1679 if (!c)
return NULL;
1733 if (subcs)
goto check_for_loop;
1741 if (!cs)
return NULL;
1755 if (!subcs)
return NULL;
1757 goto check_for_loop;
1775 if (!subcs)
return NULL;
1804 &(
section_name_t){ .name1 = unlang_ctx->section_name1, .name2 = unlang_ctx->section_name2 },
1815 cf_log_err(ci,
"The '%s' module can only be used within a '%s' namespace.",
1817 cf_log_err(ci,
"Please use the 'subrequest' keyword to change namespaces");
1841 "but no inst_size set",
1851 .type = CALL_ENV_CTX_TYPE_MODULE,
1853 .asked = &m->mmc.asked
1902 cf_log_err(ci,
"Local variable '%s' cannot be a list reference.",
name);
1914 cf_log_err(ci,
"Local variable '%s' cannot be an unlang keyword.",
name);
1922 cf_log_err(ci,
"Local variable '%s' cannot be an existing protocol name.",
name);
1933 cf_log_err(ci,
"Local variable '%s' duplicates a dictionary attribute.",
name);
1982 char const *
name, *p;
1984 char const *realname;
1988 bool ignore_notfound =
false;
2002 cf_log_err(ci,
"Syntax error after keyword '%s' - unexpected '{'",
name);
2007 goto allocate_number;
2011 goto check_for_module;
2037 cf_log_err(ci,
"Syntax error after keyword '%s' - missing '{'",
name);
2042 goto allocate_number;
2057 if (
name[0] ==
'%') {
2059 goto allocate_number;
2062 goto check_for_module;
2065 cf_log_err(ci,
"Asked to compile unknown configuration item");
2103 p = strrchr(
name,
'.');
2124 goto allocate_number;
2132 cf_log_err(ci,
"Failed compiling \"%s\" as a module or policy as no modules are enabled",
name);
2133 cf_log_err(ci,
"Please verify that modules { ... } section is present in the server configuration");
2142 if (*realname ==
'-') {
2143 ignore_notfound =
true;
2156 if (ignore_notfound) {
2157 cf_log_warn(ci,
"Ignoring \"%s\" as the \"%s\" module is not enabled, "
2158 "or the method does not exist",
name, realname);
2166 if (!c)
return NULL;
2179 cf_log_err(ci,
"Instruction \"%s\" number %u has conflict with previous one.",
2204 char const *name1, *name2;
2220 if (!name2) name2 =
"";
2222 cf_log_debug(cs,
"Compiling policies in - %s %s {...}", name1, name2);
2228 memset(&my_rules, 0,
sizeof(my_rules));
2237 .actions = *actions,
2253 if (instruction) *instruction = c;
2419 t->tracking.running_total =
fr_time_delta_add(t->tracking.running_total, frame->tracking.running_total);
2420 t->tracking.waiting_total =
fr_time_delta_add(t->tracking.waiting_total, frame->tracking.waiting_total);
2431 if (!instruction || !instruction->
number)
return;
2460 fr_log(log,
L_DBG,
file,
line,
"count=%" PRIu64
" cpu_time=%" PRId64
" yielded_time=%" PRId64 ,
2463 if (!unlang_list_empty(&g->
children)) {
2465 unlang_perf_dump(log, child,
depth + 1);
2478void unlang_perf_virtual_server(
fr_log_t *log,
char const *
name)
2502 char const *name1, *name2;
2509 if (!instruction)
continue;
2523 unlang_perf_dump(log, instruction, 2);
static int const char char buffer[256]
#define L(_str)
Helper for initialising arrays of string literals.
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
static int invalid_type(fr_type_t type)
call_env_t * call_env_alloc(TALLOC_CTX *ctx, char const *name, call_env_method_t const *call_env_method, tmpl_rules_t const *t_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...
size_t inst_size
Size of per call env.
#define RULES_VERIFY(_cs, _rules)
CONF_ITEM * cf_reference_item(CONF_SECTION const *parent_cs, CONF_SECTION const *outer_cs, char const *ptr)
Internal data that is associated with a configuration section.
Common header for all CONF_* types.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
fr_token_t cf_pair_attr_quote(CONF_PAIR const *pair)
Return the value (lhs) quoting of a pair.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
bool cf_item_is_data(CONF_ITEM const *ci)
Determine if CONF_ITEM is CONF_DATA.
fr_token_t cf_pair_operator(CONF_PAIR const *pair)
Return the operator of a pair.
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
fr_token_t cf_section_name2_quote(CONF_SECTION const *cs)
Return the quoting of the name2 identifier.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
CONF_ITEM * cf_pair_to_item(CONF_PAIR const *cp)
Cast a CONF_PAIR to a CONF_ITEM.
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
#define cf_data_add(_cf, _data, _name, _free)
#define cf_data_find(_cf, _type, _name)
#define cf_log_debug_prefix(_cf, _fmt,...)
#define cf_data_remove(_cf, _type, _name)
Remove an item from a parent by type and name.
#define cf_section_free_children(_x)
#define cf_canonicalize_error(_ci, _slen, _msg, _str)
#define cf_item_next(_parent, _curr)
#define cf_log_perr(_cf, _fmt,...)
#define CF_TO_ITEM(_cf)
Auto cast from the input type to CONF_ITEM (which is the base type)
#define cf_log_warn(_cf, _fmt,...)
#define cf_log_debug(_cf, _fmt,...)
static int compile_action_pair(unlang_mod_actions_t *actions, CONF_PAIR *cp)
unlang_t * unlang_compile_children(unlang_group_t *g, unlang_compile_ctx_t *unlang_ctx_in)
static unlang_t * compile_module(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_ITEM *ci, char const *name)
static unlang_t * compile_edit_pair(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_PAIR *cp)
Compile one edit pair.
bool unlang_compile_is_keyword(const char *name)
Check if name is an unlang keyword.
void unlang_compile_init(TALLOC_CTX *ctx)
unlang_t * unlang_compile_section(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_SECTION *cs, unlang_type_t type)
bool unlang_compile_actions(unlang_mod_actions_t *actions, CONF_SECTION *action_cs, bool module_retry)
bool pass2_fixup_map_rhs(unlang_group_t *g, tmpl_rules_t const *rules)
bool pass2_fixup_tmpl(UNUSED TALLOC_CTX *ctx, tmpl_t **vpt_p, CONF_ITEM const *ci, fr_dict_t const *dict)
static unlang_t * compile_edit_section(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_SECTION *cs)
Compile one edit section.
bool unlang_compile_limit_subsection(CONF_SECTION *cs, char const *name)
int unlang_thread_instantiate(TALLOC_CTX *ctx)
Create thread-specific data structures for unlang.
static void unlang_dump(unlang_t *c, int depth)
static int compile_variable(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_PAIR *cp, tmpl_rules_t *t_rules)
Compile a variable definition.
static char const unlang_spaces[]
static int8_t instruction_cmp(void const *one, void const *two)
int unlang_fixup_update(map_t *map, void *ctx)
Validate and fixup a map that's part of an update section.
static bool compile_retry_section(unlang_mod_actions_t *actions, CONF_ITEM *ci)
static CONF_SECTION * virtual_module_find_cs(CONF_ITEM *ci, UNUSED char const *real_name, char const *virtual_name, char const *method_name, unlang_compile_ctx_t *unlang_ctx, bool *policy)
Load a named module from the virtual module list, or from the "policy" subsection.
static unlang_t * compile_item(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_ITEM *ci)
static const bool edit_list_sub_op[T_TOKEN_LAST]
size_t mod_rcode_table_len
static unlang_t * compile_tmpl(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_ITEM *ci)
static void compile_set_default_actions(unlang_t *c, unlang_compile_ctx_t *unlang_ctx)
Update a compiled unlang_t with the default actions.
static unsigned int unlang_number
unlang_t * unlang_compile_empty(unlang_t *parent, UNUSED unlang_compile_ctx_t *unlang_ctx, CONF_SECTION *cs, unlang_type_t type)
unlang_group_t * unlang_group_allocate(unlang_t *parent, CONF_SECTION *cs, unlang_type_t type)
#define debug_braces(_type)
bool pass2_fixup_map(map_t *map, tmpl_rules_t const *rules, fr_dict_attr_t const *parent)
Fixup ONE map (recursively)
static fr_rb_tree_t * unlang_instruction_tree
bool pass2_fixup_update(unlang_group_t *g, tmpl_rules_t const *rules)
static unlang_t * compile_function(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_ITEM *ci, CONF_SECTION *subcs, bool policy)
int dict_attr_acopy_children(fr_dict_t *dict, fr_dict_attr_t *dst, fr_dict_attr_t const *src)
Copy the children of an existing attribute.
fr_table_num_sorted_t const mod_rcode_table[]
void * unlang_thread_instance(unlang_t const *instruction)
Get the thread-instance data for an instruction.
static int unlang_fixup_edit(map_t *map, void *ctx)
Validate and fixup a map that's part of an edit section.
int unlang_compile(virtual_server_t const *vs, CONF_SECTION *cs, unlang_mod_actions_t const *actions, tmpl_rules_t const *rules, void **instruction)
Compile an unlang section for a virtual server.
static _Thread_local unlang_thread_t * unlang_thread_array
static unlang_op_t const * name_to_op(char const *name)
#define CLAMP(_name, _field, _limit)
int unlang_define_local_variable(CONF_ITEM *ci, unlang_variable_t *var, tmpl_rules_t *t_rules, fr_type_t type, char const *name, fr_dict_attr_t const *ref)
static bool compile_action_subsection(unlang_t *c, CONF_SECTION *cs, CONF_SECTION *subcs)
static unlang_cond_t * unlang_group_to_cond(unlang_group_t *g)
Cast a group structure to the cond keyword extension.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
#define fr_fatal_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
int fr_dict_attr_acopy_local(fr_dict_attr_t const *dst, fr_dict_attr_t const *src)
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
bool fr_dict_compatible(fr_dict_t const *dict1, fr_dict_t const *dict2)
See if two dictionaries have the same end parent.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
unsigned int internal
Internal attribute, should not be received in protocol packets, should not be encoded.
fr_dict_t const * fr_dict_by_protocol_name(char const *name)
Lookup a protocol by its name.
int fr_dict_attr_add(fr_dict_t *dict, fr_dict_attr_t const *parent, char const *name, unsigned int attr, fr_type_t type, fr_dict_attr_flags_t const *flags))
Add an attribute to the dictionary.
fr_dict_t * fr_dict_protocol_alloc(fr_dict_t const *parent)
Allocate a new local dictionary.
Values of the encryption flags.
map_list_t maps
Head of the map list.
static unlang_t * unlang_edit_to_generic(unlang_edit_t const *p)
static unlang_edit_t * unlang_generic_to_edit(unlang_t const *p)
Cast a generic structure to the edit extension.
void * fr_hash_table_find(fr_hash_table_t *ht, void const *data)
Find data in a hash table.
#define DEBUG_ENABLED4
True if global debug level 1-3 messages are enabled.
int map_afrom_cs_edit(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 for editing.
int map_afrom_cp(TALLOC_CTX *ctx, map_t **out, map_t *parent, CONF_PAIR *cp, tmpl_rules_t const *lhs_rules, tmpl_rules_t const *input_rhs_rules, bool edit)
Convert CONFIG_PAIR (which may contain refs) to map_t.
int map_list_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, CONF_SECTION *cs, tmpl_rules_t const *t_rules, map_validate_t validate, void *uctx, unsigned int max)
Convert a config section into a list of { a, b, c, d, ... }.
ssize_t map_print(fr_sbuff_t *out, map_t const *map)
Print a map to a string.
unlang_op_t unlang_ops[UNLANG_TYPE_MAX]
Different operations the interpreter can execute.
static TALLOC_CTX * unlang_ctx
fr_hash_table_t * unlang_op_table
void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt,...)
Send a server log message to its destination.
@ L_DBG
Only displayed when debugging is enabled.
static unlang_map_t * unlang_group_to_map(unlang_group_t *g)
Cast a group structure to the map keyword extension.
map_list_t map
Head of the map list.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_GROUP
A grouping of other attributes.
static uint8_t depth(fr_minmax_heap_index_t i)
int strcasecmp(char *s1, char *s2)
@ MOD_ACTION_RETURN
stop processing the section, and return the rcode with unset priority
@ MOD_ACTION_REJECT
change the rcode to REJECT, with unset priority
@ MOD_ACTION_RETRY
retry the instruction, MUST also set a retry config
#define MOD_ACTION_VALID_SET(_x)
unlang_mod_action_t actions[RLM_MODULE_NUMCODES]
Declarations for the unlang module interface.
static unlang_t * unlang_module_to_generic(unlang_module_t *p)
static unlang_module_t * unlang_generic_to_module(unlang_t const *p)
module_method_call_t mmc
Everything needed to call a module method.
unlang_t self
Common fields in all unlang_t tree nodes.
call_env_t const * call_env
The per call parsed call environment.
A call to a module method.
fr_slen_t module_rlm_by_name_and_method(TALLOC_CTX *ctx, module_method_call_t *mmc_out, virtual_server_t const *vs, section_name_t const *section, fr_sbuff_t *name, tmpl_rules_t const *t_rules)
Find an existing module instance and verify it implements the specified method.
CONF_SECTION * module_rlm_virtual_by_name(char const *asked_name)
module_instance_t * mi
The process modules also push module calls onto the stack for execution.
module_t common
Common fields presented by all modules.
module_method_binding_t mmb
Method we're calling.
module_rlm_t const * rlm
Cached module_rlm_t.
Declarations for the unlang "parallel" keyword.
void * fr_rb_iter_init_inorder(fr_rb_iter_inorder_t *iter, fr_rb_tree_t *tree)
Initialise an in-order iterator.
void * fr_rb_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
#define fr_rb_alloc(_ctx, _data_cmp, _data_free)
Allocs a red black tree.
Iterator structure for in-order traversal of an rbtree.
The main red black tree structure.
@ RLM_MODULE_INVALID
The module considers the request invalid.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
@ RLM_MODULE_REJECT
Immediately reject the request.
@ RLM_MODULE_TIMEOUT
Module (or section) timed out.
@ RLM_MODULE_NOTFOUND
User not found.
@ RLM_MODULE_UPDATED
OK (pairs modified).
@ RLM_MODULE_NOT_SET
Error resolving rcode (should not be returned by modules).
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
@ RLM_MODULE_NUMCODES
How many valid return codes there are.
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
static const call_env_method_t method_env
#define FR_SBUFF_IN(_start, _len_or_end)
#define FR_SBUFF_OUT(_start, _len_or_end)
char const * name
Instance name e.g. user_database.
@ MODULE_TYPE_RETRY
can handle retries
module_flags_t flags
Flags that control how a module starts up and how a module is called.
CONF_SECTION * conf
Module's instance configuration.
unlang_mod_actions_t actions
default actions and retries.
fr_dict_t const ** dict
required dictionary for this module.
call_env_method_t const * method_env
Method specific call_env.
module_t * exported
Public module structure.
static int16_t tmpl_attr_tail_num(tmpl_t const *vpt)
Return the last attribute reference's attribute number.
#define TMPL_VERIFY(_vpt)
static char const * tmpl_type_to_str(tmpl_type_t type)
Return a static string containing the type name.
#define tmpl_is_xlat(vpt)
int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules))
Attempt to resolve functions and attributes in xlats and attribute references.
fr_table_num_sorted_t const tmpl_request_ref_table[]
Map keywords to tmpl_request_ref_t values.
#define tmpl_is_attr(vpt)
tmpl_rules_t const * parent
for parent / child relationships
ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, char const *name, tmpl_rules_t const *rules))
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
@ TMPL_TYPE_XLAT
Pre-parsed xlat expansion.
@ TMPL_TYPE_EXEC
Callout to an external script or program.
@ TMPL_TYPE_DATA
Value in native boxed format.
@ TMPL_TYPE_DATA_UNRESOLVED
Unparsed literal string.
@ TMPL_TYPE_XLAT_UNRESOLVED
A xlat expansion with unresolved xlat functions or attribute references.
static bool tmpl_attr_tail_da_is_leaf(tmpl_t const *vpt)
Return true if the the last attribute reference is a leaf attribute.
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 bool tmpl_is_list(tmpl_t const *vpt)
int tmpl_cast_in_place(tmpl_t *vpt, fr_type_t type, fr_dict_attr_t const *enumv))
Convert tmpl_t of type TMPL_TYPE_DATA_UNRESOLVED or TMPL_TYPE_DATA to TMPL_TYPE_DATA of type specifie...
static size_t tmpl_attr_num_elements(tmpl_t const *vpt)
The number of attribute references contained within a tmpl.
void tmpl_attr_rewrite_leaf_num(tmpl_t *vpt, int16_t num)
Rewrite the leaf's instance number.
#define tmpl_is_data_unresolved(vpt)
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
@ REQUEST_UNKNOWN
Unknown request.
#define tmpl_is_regex_xlat_unresolved(vpt)
void tmpl_set_dict_def(tmpl_t *vpt, fr_dict_t const *dict)
Change the default dictionary in the tmpl's resolution rules.
fr_slen_t tmpl_attr_list_from_substr(fr_dict_attr_t const **da_p, fr_sbuff_t *in)
Parse one a single list reference.
Similar to tmpl_rules_t, but used to specify parameters that may change during subsequent resolution ...
Optional arguments passed to vp_tmpl functions.
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
fr_aka_sim_id_type_t type
#define fr_time()
Allow us to arbitrarily manipulate time.
size_t strlcpy(char *dst, char const *src, size_t siz)
fr_token_t op
The operator that controls insertion of the dst attribute.
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
map_list_t child
parent map, for nested ones
tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
CONF_ITEM * ci
Config item that the map was created from.
fr_dict_attr_t const * list_def
Default list to use with unqualified attribute reference.
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
uint8_t allow_unknown
Allow unknown attributes i.e.
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
An element in a lexicographically sorted array of name to num mappings.
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
fr_slen_t fr_time_delta_from_str(fr_time_delta_t *out, char const *in, size_t inlen, fr_time_res_t hint)
Create fr_time_delta_t from a string.
static fr_time_delta_t fr_time_delta_add(fr_time_delta_t a, fr_time_delta_t b)
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
#define fr_time_delta_ispos(_a)
@ FR_TIME_TRACKING_YIELDED
We're currently tracking time in the yielded state.
static void fr_time_tracking_yield(fr_time_tracking_t *tt, fr_time_t now)
Transition to the yielded state, recording the time we just spent running.
static void fr_time_tracking_end(fr_time_delta_t *predicted, fr_time_tracking_t *tt, fr_time_t now)
End time tracking for this entity.
static void fr_time_tracking_start(fr_time_tracking_t *parent, fr_time_tracking_t *tt, fr_time_t now)
Start time tracking for a tracked entity.
static void fr_time_tracking_resume(fr_time_tracking_t *tt, fr_time_t now)
Track that a request resumed.
const bool fr_assignment_op[T_TOKEN_LAST]
const bool fr_list_assignment_op[T_TOKEN_LAST]
fr_table_num_ordered_t const fr_tokens_table[]
char const * fr_tokens[T_TOKEN_LAST]
const bool fr_comparison_op[T_TOKEN_LAST]
const bool fr_binary_op[T_TOKEN_LAST]
Declarations for unlang transactions.
Declaration for unlang try.
#define unlang_frame_perf_resume(_x)
char const * debug_name
Printed in log messages when the node is executed.
void * state
Stack frame specialisations.
unlang_mod_actions_t actions
Priorities, etc. for the various return codes.
tmpl_rules_t const * rules
unlang_t * parent
Previous node.
static void unlang_type_init(unlang_t *unlang, unlang_t *parent, unlang_type_t type)
char const * thread_inst_type
fr_dict_attr_t const * root
the root of our dictionary
size_t pool_len
How much additional space to allocate for chunks.
static void unlang_compile_ctx_copy(unlang_compile_ctx_t *dst, unlang_compile_ctx_t const *src)
#define unlang_frame_perf_init(_x)
bool closed
whether or not this section is closed to new statements
static unlang_t * unlang_group_to_generic(unlang_group_t const *p)
#define unlang_list_foreach(_list_head, _iter)
char const * unlang_name
Talloc type name for the unlang_t.
static unlang_t * unlang_tmpl_to_generic(unlang_tmpl_t const *p)
CONF_ITEM * ci
used to generate this item
static unlang_group_t * unlang_generic_to_group(unlang_t const *p)
unsigned int number
unique node number
size_t unlang_size
Total length of the unlang_t + specialisation struct.
char const * name
Unknown...
unlang_type_t
Types of unlang_t nodes.
@ UNLANG_TYPE_SWITCH
Switch section.
@ UNLANG_TYPE_TRANSACTION
transactions for editing lists
@ UNLANG_TYPE_FINALLY
run at the end of a virtual server.
@ UNLANG_TYPE_SUBREQUEST
create a child subrequest
@ UNLANG_TYPE_CONTINUE
Break statement (within a UNLANG_TYPE_FOREACH).
@ UNLANG_TYPE_UPDATE
Update block.
@ UNLANG_TYPE_ELSIF
!Condition && Condition.
@ UNLANG_TYPE_ELSE
!Condition.
@ UNLANG_TYPE_LOAD_BALANCE
Load balance section.
@ UNLANG_TYPE_DETACH
detach a child
@ UNLANG_TYPE_GROUP
Grouping section.
@ UNLANG_TYPE_POLICY
Policy section.
@ UNLANG_TYPE_TMPL
asynchronously expand a tmpl_t
@ UNLANG_TYPE_CASE
Case section (within a UNLANG_TYPE_SWITCH).
@ UNLANG_TYPE_LIMIT
limit number of requests in a section
@ UNLANG_TYPE_BREAK
Break statement (within a UNLANG_TYPE_FOREACH or UNLANG_TYPE_CASE).
@ UNLANG_TYPE_TRY
try / catch blocks
@ UNLANG_TYPE_CALL
call another virtual server
@ UNLANG_TYPE_RETURN
Return statement.
@ UNLANG_TYPE_REDUNDANT
exactly like group, but with different default return codes
@ UNLANG_TYPE_IF
Condition.
@ UNLANG_TYPE_XLAT
Represents one level of an xlat expansion.
@ UNLANG_TYPE_NULL
unlang type not set.
@ UNLANG_TYPE_MAP
Mapping section (like UNLANG_TYPE_UPDATE, but uses values from a map_proc_t call).
@ UNLANG_TYPE_CALLER
conditionally check parent dictionary type
@ UNLANG_TYPE_TIMEOUT
time-based timeouts.
@ UNLANG_TYPE_MODULE
Module method.
@ UNLANG_TYPE_REDUNDANT_LOAD_BALANCE
Redundant load balance section.
@ UNLANG_TYPE_CHILD_REQUEST
a frame at the top of a child's request stack used to signal the parent when the child is complete.
@ UNLANG_TYPE_CATCH
catch a previous try
@ UNLANG_TYPE_FUNCTION
Internal call to a function or submodule.
@ UNLANG_TYPE_EDIT
edit VPs in place. After 20 years!
@ UNLANG_TYPE_FOREACH
Foreach section.
@ UNLANG_TYPE_PARALLEL
execute statements in parallel
unlang_t const * instruction
The unlang node we're evaluating.
unsigned pool_headers
How much additional space to allocate for chunk headers.
unlang_compile_t compile
compile the keyword
unlang_variable_t * variables
rarely used, so we don't usually need it
unlang_t const * instruction
instruction which we're executing
char const * name
Name of the keyword.
#define unlang_frame_perf_yield(_x)
#define unlang_frame_perf_cleanup(_x)
int max_attr
1..N local attributes have been defined
unlang_thread_instantiate_t thread_instantiate
per-thread instantiation function
fr_dict_t * dict
our dictionary
static void unlang_group_type_init(unlang_t *unlang, unlang_t *parent, unlang_type_t type)
@ UNLANG_OP_FLAG_SINGLE_WORD
the operation is parsed and compiled as a single word
unlang_type_t type
The specialisation of this node.
unlang_op_flag_t flag
Interpreter flags for this operation.
unlang_list_t * list
so we have fewer run-time dereferences
void * thread_inst
thread-specific instance data
Generic representation of a grouping.
A node in a graph of unlang_op_t (s) that we execute.
Our interpreter stack, as distinct from the C stack.
fr_time_delta_t irt
Initial transmission time.
fr_time_delta_t mrt
Maximum retransmission time.
uint32_t mrc
Maximum retransmission count.
fr_time_delta_t mrd
Maximum retransmission duration.
char const * fr_strerror(void)
Get the last library error.
#define fr_strerror_const(_msg)
fr_table_num_ordered_t const fr_type_table[]
Map data types to names representing those types.
#define fr_type_is_structural(_x)
#define fr_type_is_leaf(_x)
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
#define DOC_KEYWORD_REF(_x)
static size_t char ** out
virtual_server_t const * virtual_server_find(char const *name)
Return virtual server matching the specified name.
CONF_SECTION * virtual_server_cs(virtual_server_t const *vs)
Return the configuration section for a virtual server.