vb = fr_value_box_list_head(tmpl_expanded);
if (!vb) {
- if (!env->rule->pair.nullable) {
+ if (!call_env_nullable(env->rule->flags)) {
RPEDEBUG("Failed to evaluate required module option %s = %s", env->rule->name, env->tmpl->name);
return CALL_ENV_MISSING;
}
/*
* Concatenate multiple boxes if needed
*/
- if (env->rule->pair.concat &&
- fr_value_box_list_concat_in_place(vb, vb, tmpl_expanded, env->rule->type,
+ if (call_env_concat(env->rule->flags) &&
+ fr_value_box_list_concat_in_place(vb, vb, tmpl_expanded, env->rule->pair.cast_type,
FR_VALUE_BOX_LIST_FREE, true, SIZE_MAX) < 0 ) {
RPEDEBUG("Failed concatenating values for %s", env->rule->name);
return CALL_ENV_INVALID;
}
- if (env->rule->pair.single && (fr_value_box_list_num_elements(tmpl_expanded) > 1)) {
+ if (call_env_single(env->rule->flags) && (fr_value_box_list_num_elements(tmpl_expanded) > 1)) {
RPEDEBUG("%d values found for %s. Only one is allowed",
fr_value_box_list_num_elements(tmpl_expanded), env->rule->name);
return CALL_ENV_INVALID;
/*
* If we only need the tmpl, just set the pointer and move the next.
*/
- out = (void **)((uint8_t *)*call_env_rctx->data + env->rule->pair.tmpl_offset);
+ out = (void **)((uint8_t *)*call_env_rctx->data + env->rule->parsed_offset);
*out = env->tmpl;
}
/*
* Multi pair options should allocate boxes in the context of the array
*/
- if (env->rule->pair.multi) {
- out = (void **)((uint8_t *)(*call_env_rctx->data) + env->rule->offset);
+ if (call_env_multi(env->rule->flags)) {
+ out = (void **)((uint8_t *)(*call_env_rctx->data) + env->rule->pair.result_offset);
/*
* For multi pair options, allocate the array before expanding the first entry.
/*
* Find the location of the output
*/
- out = ((uint8_t*)(*call_env_rctx->data)) + env->rule->offset;
+ out = ((uint8_t*)(*call_env_rctx->data)) + env->rule->pair.result_offset;
/*
* If this is a multi pair option, the output is an array.
* Find the correct offset in the array
*/
- if (env->rule->pair.multi) {
+ if (call_env_multi(env->rule->flags)) {
void *array = *(void **)out;
out = ((uint8_t *)array) + env->rule->pair.size * env->multi_index;
}
tmpl_only:
- if (env->rule->pair.tmpl_offset >= 0) tmpl_out = ((uint8_t *)*call_env_rctx->data) + env->rule->pair.tmpl_offset;
+ if (env->rule->parsed_offset >= 0) tmpl_out = ((uint8_t *)*call_env_rctx->data) + env->rule->parsed_offset;
result = call_env_value_parse(*call_env_rctx->data, request, out, tmpl_out, env, &call_env_rctx->tmpl_expanded);
if (result != CALL_ENV_SUCCESS) {
fr_type_t type;
while (call_env->name) {
- if (call_env->flags & CONF_FLAG_SUBSECTION) {
+ if (call_env_is_subsection(call_env->flags)) {
CONF_SECTION const *subcs;
subcs = cf_section_find(cs, call_env->name, call_env->section.ident2);
if (!subcs) {
- if (!call_env->section.required) goto next;
+ if (!call_env_required(call_env->flags)) goto next;
cf_log_err(cs, "Module %s missing required section %s", name, call_env->name);
return -1;
}
cp = cf_pair_find(cs, call_env->name);
- if (!cp && !call_env->dflt) {
- if (!call_env->pair.required) goto next;
+ if (!cp && !call_env->pair.dflt) {
+ if (!call_env_required(call_env->flags)) goto next;
cf_log_err(cs, "Module %s missing required option %s", name, call_env->name);
return -1;
* Check for additional conf pairs and error
* if there is one and multi is not allowed.
*/
- if (!call_env->pair.multi && ((next = cf_pair_find_next(cs, cp, call_env->name)))) {
+ if (!call_env_multi(call_env->flags) && ((next = cf_pair_find_next(cs, cp, call_env->name)))) {
cf_log_err(cf_pair_to_item(next), "Invalid duplicate configuration item '%s'", call_env->name);
return -1;
}
if (cp) {
value = cf_pair_value(cp);
len = talloc_array_length(value) - 1;
- quote = call_env->pair.force_quote ? call_env->dflt_quote : cf_pair_value_quote(cp);
+ quote = call_env_force_quote(call_env->flags) ? call_env->pair.dflt_quote : cf_pair_value_quote(cp);
} else {
- value = call_env->dflt;
+ value = call_env->pair.dflt;
len = strlen(value);
- quote = call_env->dflt_quote;
+ quote = call_env->pair.dflt_quote;
}
- type = call_env->type;
+ type = call_env->pair.cast_type;
if (tmpl_afrom_substr(call_env_parsed, &call_env_parsed->tmpl, &FR_SBUFF_IN(value, len),
quote, NULL, &(tmpl_rules_t){
.cast = (type == FR_TYPE_VOID ? FR_TYPE_NULL : type),
case TMPL_TYPE_DATA:
case TMPL_TYPE_EXEC:
case TMPL_TYPE_XLAT:
- if (call_env->type & CONF_FLAG_ATTRIBUTE) {
+ if (call_env_attribute(call_env->flags)) {
cf_log_perr(cp, "'%s' expands to %s - attribute reference required", value,
fr_table_str_by_value(tmpl_type_table, call_env_parsed->tmpl->type,
"<INVALID>"));
*names_len = 0;
while (call_env->name) {
- if (call_env->flags & CONF_FLAG_SUBSECTION) {
+ if (call_env_is_subsection(call_env->flags)) {
CONF_SECTION const *subcs;
subcs = cf_section_find(cs, call_env->name, call_env->section.ident2);
if (!subcs) goto next;
pair_count++;
*names_len += talloc_array_length(cf_pair_value(cp));
}
- if (!pair_count && call_env->dflt) {
+ if (!pair_count && call_env->pair.dflt) {
pair_count = 1;
- *names_len += strlen(call_env->dflt);
+ *names_len += strlen(call_env->pair.dflt);
}
tmpl_count += pair_count;
next:
CALL_ENV_TYPE_VALUE_BOX = 1,
CALL_ENV_TYPE_VALUE_BOX_LIST,
CALL_ENV_TYPE_TMPL_ONLY
-} call_env_dest_t;
+} call_env_dst_t;
+
+DIAG_OFF(attributes)
+typedef enum CC_HINT(flag_enum) {
+ CALL_ENV_FLAG_NONE = 0,
+ CALL_ENV_FLAG_REQUIRED = 1, //!< Tmpl must produce output or section is required.
+ CALL_ENV_FLAG_CONCAT = (1 << 1), //!< If the tmpl produced multiple boxes they should be concatenated.
+ CALL_ENV_FLAG_SINGLE = (1 << 2), //!< If the tmpl produces more than one box this is an error.
+ CALL_ENV_FLAG_MULTI = (1 << 3), //!< Multiple instances of the conf pairs are allowed. Resulting
+ ///< boxes are stored in an array - one entry per conf pair.
+ CALL_ENV_FLAG_NULLABLE = (1 << 4), //!< Tmpl expansions are allowed to produce no output.
+ CALL_ENV_FLAG_FORCE_QUOTE = (1 << 5), //!< Force quote method when parsing tmpl. This is for corner cases
+ ///< where tmpls should always be parsed with a particular quoting
+ ///< regardless of how they are in the config file. E.g. the `program`
+ ///< option of `rlm_exec` should always be parsed as T_BACK_QUOTED_STRING.
+ CALL_ENV_FLAG_ATTRIBUTE = (1 << 6), //!< Tmpl must contain an attribute reference.
+ CALL_ENV_FLAG_SUBSECTION = (1 << 7) //!< This is a subsection.
+} call_env_flags_t;
+DIAG_ON(attributes)
+
+
+/** @name #conf_parser_t flags checks
+ *
+ * @{
+ */
+/** Evaluates to true if flags are valid for a pair
+ *
+ * @param[in] _flags to evaluate
+ */
+#define call_env_pair_flags(_flags) (((_flags) & (CALL_ENV_FLAG_SUBSECTION)) == 0)
+
+/** Evaluates to true if flags are valid for a subsection
+ *
+ * @param[in] _flags to evaluate
+ */
+#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)) == 0)
+
+#define call_env_required(_flags) ((_flags) & CALL_ENV_FLAG_REQUIRED)
+
+#define call_env_concat(_flags) ((_flags) & CALL_ENV_FLAG_CONCAT)
+
+#define call_env_single(_flags) ((_flags) & CALL_ENV_FLAG_SINGLE)
+
+#define call_env_multi(_flags) ((_flags) & CALL_ENV_FLAG_MULTI)
+
+#define call_env_nullable(_flags) ((_flags) & CALL_ENV_FLAG_NULLABLE)
+
+#define call_env_force_quote(_flags) ((_flags) & CALL_ENV_FLAG_FORCE_QUOTE)
+
+#define call_env_attribute(_flags) ((_flags) & CALL_ENV_FLAG_ATTRIBUTE)
+
+#define call_env_is_subsection(_flags) ((_flags) & CALL_ENV_FLAG_SUBSECTION)
+/** @} */
/** Per method call config
*
* and use the appropriate dictionaries for where the module is in use.
*/
struct call_env_parser_s {
- char const *name; //!< Of conf pair to pass to tmpl_tokenizer.
- char const *dflt; //!< Default string to pass to the tmpl_tokenizer if no CONF_PAIR found.
- fr_token_t dflt_quote; //!< Default quoting for the default string.
+ char const *name; //!< Of conf pair to pass to tmpl_tokenizer.
+ call_env_flags_t flags; //!< Flags controlling parser behaviour.
- fr_type_t type; //!< To cast boxes to. Also contains flags controlling parser behaviour.
- conf_parser_flags_t flags; //!< Flags controlling parser behaviour.
-
- size_t offset; //!< Where to write results in the output structure when the tmpls are evaluated.
+ ssize_t parsed_offset; //!< Where to write the result of the parsing phase.
+ ///< This is usually a tmpl_t, but could be other things when a callback
+ ///< function is used to parse the CONF_SECTION or CONF_PAIR.
union {
struct {
- bool required; //!< Tmpl must produce output
- bool concat; //!< If the tmpl produced multiple boxes they should be concatenated.
- bool single; //!< If the tmpl produces more than one box this is an error.
- bool multi; //!< Multiple instances of the conf pairs are allowed. Resulting
- ///< boxes are stored in an array - one entry per conf pair.
- bool nullable; //!< Tmpl expansions are allowed to produce no output.
- bool force_quote; //!< Force quote method when parsing tmpl. This is for corner cases
- ///< where tmpls should always be parsed with a particular quoting
- ///< regardless of how they are in the config file. E.g. the `program`
- ///< option of `rlm_exec` should always be parsed as T_BACK_QUOTED_STRING.
- call_env_dest_t type; //!< Type of structure boxes will be written to.
- size_t size; //!< Size of structure boxes will be written to.
- char const *type_name; //!< Name of structure type boxes will be written to.
- ssize_t tmpl_offset; //!< Where to write pointer to tmpl in the output structure. Optional.
+ fr_type_t cast_type; //!< To cast boxes to. Also contains flags controlling parser behaviour.
+
+ call_env_dst_t type; //!< Type of structure boxes will be written to.
+ size_t size; //!< Size of structure boxes will be written to.
+ char const *type_name; //!< Name of structure type boxes will be written to.
+ size_t result_offset; //!< Where to write the result of evaluating the tmpl_t produced in the parsing phase.
+
+ char const *dflt; //!< Default string to pass to the tmpl_tokenizer if no CONF_PAIR found.
+ fr_token_t dflt_quote; //!< Quoting for the default string.
} pair;
struct {
char const *ident2; //!< Second identifier for a section
call_env_parser_t const *subcs; //!< Nested definitions for subsection.
- bool required; //!< Section is required.
} section;
};
};
*/
#define FR_CALL_ENV_SINGLE(_s, _f, _c) \
_Generic((((_s *)NULL)->_f), \
- fr_value_box_t : __builtin_choose_expr(_c, false, true), \
- fr_value_box_t * : __builtin_choose_expr(_c, false, true), \
- fr_value_box_list_t : false, \
- fr_value_box_list_t * : false \
+ fr_value_box_t : __builtin_choose_expr(_c, CALL_ENV_FLAG_NONE, CALL_ENV_FLAG_SINGLE), \
+ fr_value_box_t * : __builtin_choose_expr(_c, CALL_ENV_FLAG_NONE, CALL_ENV_FLAG_SINGLE), \
+ fr_value_box_list_t : CALL_ENV_FLAG_NONE, \
+ fr_value_box_list_t * : CALL_ENV_FLAG_SINGLE \
)
/** Derive whether multi conf pairs are allowed from target field type.
*/
#define FR_CALL_ENV_MULTI(_s, _f) \
_Generic((((_s *)NULL)->_f), \
- fr_value_box_t : false, \
- fr_value_box_t * : true, \
- fr_value_box_list_t : false, \
- fr_value_box_list_t * : true \
+ fr_value_box_t : CALL_ENV_FLAG_NONE, \
+ fr_value_box_t * : CALL_ENV_FLAG_MULTI, \
+ fr_value_box_list_t : CALL_ENV_FLAG_NONE, \
+ fr_value_box_list_t * : CALL_ENV_FLAG_MULTI \
)
/** Only FR_TYPE_STRING and FR_TYPE_OCTETS can be concatenated.
fr_value_box_list_t * : "fr_value_box_list_t" \
)
-#define FR_CALL_ENV_OFFSET(_name, _cast_type, _flags, _struct, _field, _dflt, _dflt_quote, _required, _nullable, _concat) \
+typedef void _mismatch_flags; //!< Dummy type used to indicate bad flags.
+
+#define CALL_ENV_FLAGS(_cast_type, _flags, _struct, _field) \
+ (FR_CALL_ENV_CONCAT((_flags & CALL_ENV_FLAG_CONCAT), _cast_type) | \
+ FR_CALL_ENV_SINGLE(_struct, _field, (_flags & CALL_ENV_FLAG_CONCAT)) | \
+ FR_CALL_ENV_MULTI(_struct, _field) |\
+ ((_flags) & ~CALL_ENV_FLAG_CONCAT)) \
+
+#define FR_CALL_ENV_OFFSET(_name, _cast_type, _flags, _struct, _field) \
.name = _name, \
- .type = _cast_type, \
- .offset = offsetof(_struct, _field), \
- .dflt = _dflt, \
- .dflt_quote = _dflt_quote, \
+ .flags = CALL_ENV_FLAGS(_cast_type, _flags, _struct, _field), \
+ .parsed_offset = -1, \
.pair = { \
- .required = _required, \
- .concat = FR_CALL_ENV_CONCAT(_concat, _cast_type), \
- .single = FR_CALL_ENV_SINGLE(_struct, _field, _concat), \
- .multi = FR_CALL_ENV_MULTI(_struct, _field), \
- .nullable = _nullable, \
+ .cast_type = _cast_type, \
.type = FR_CALL_ENV_DST_TYPE(_struct, _field), \
.size = FR_CALL_ENV_DST_SIZE(_struct, _field), \
.type_name = FR_CALL_ENV_DST_TYPE_NAME(_struct, _field), \
- .tmpl_offset = -1 \
+ .result_offset = offsetof(_struct, _field), \
}
/** Version of the above which sets optional field for pointer to tmpl
*/
-#define FR_CALL_ENV_TMPL_OFFSET(_name, _cast_type, _flags, _struct, _field, _tmpl_field, _dflt, _dflt_quote, _required, _nullable, _concat) \
+#define FR_CALL_ENV_TMPL_OFFSET(_name, _cast_type, _flags, _struct, _field, _tmpl_field) \
.name = _name, \
- .type = _cast_type, \
- .offset = offsetof(_struct, _field), \
- .dflt = _dflt, \
- .dflt_quote = _dflt_quote, \
+ .flags = CALL_ENV_FLAGS(_cast_type, _flags, _struct, _field), \
+ .parsed_offset = offsetof(_struct, _tmpl_field), \
.pair = { \
- .required = _required, \
- .concat = FR_CALL_ENV_CONCAT(_concat, _cast_type), \
- .single = FR_CALL_ENV_SINGLE(_struct, _field, _concat), \
- .multi = FR_CALL_ENV_MULTI(_struct, _field), \
- .nullable = _nullable, \
+ .cast_type = _cast_type, \
.type = FR_CALL_ENV_DST_TYPE(_struct, _field), \
.size = FR_CALL_ENV_DST_SIZE(_struct, _field), \
.type_name = FR_CALL_ENV_DST_TYPE_NAME(_struct, _field), \
- .tmpl_offset = offsetof(_struct, _tmpl_field) \
+ .result_offset = offsetof(_struct, _field), \
}
/** Version of the above which only sets the field for a pointer to the tmpl
*/
-#define FR_CALL_ENV_TMPL_ONLY_OFFSET(_name, _cast_type, _flags, _struct, _tmpl_field, _dflt, _dflt_quote, _required) \
+#define FR_CALL_ENV_TMPL_ONLY_OFFSET(_name, _cast_type, _flags, _struct, _tmpl_field) \
.name = _name, \
- .type = _cast_type, \
- .dflt = _dflt, \
- .dflt_quote = _dflt_quote, \
+ .flags = _flags, \
+ .parsed_offset = offsetof(_struct, _tmpl_field), \
.pair = { \
- .required = _required, \
- .type = CALL_ENV_TYPE_TMPL_ONLY, \
- .tmpl_offset = offsetof(_struct, _tmpl_field) \
+ .cast_type = _cast_type, \
+ .type = CALL_ENV_TYPE_TMPL_ONLY \
}
-#define FR_CALL_ENV_SUBSECTION(_name, _ident2, _subcs, _required ) \
+#define FR_CALL_ENV_SUBSECTION(_name, _ident2, _flags, _subcs ) \
.name = _name, \
- .flags = CONF_FLAG_SUBSECTION, \
+ .flags = CALL_ENV_FLAG_SUBSECTION | (_flags), \
.section = { \
.ident2 = _ident2, \
.subcs = _subcs, \
- .required = _required \
}
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);
static const call_env_method_t cache_method_env = {
FR_CALL_ENV_METHOD_OUT(cache_call_env_t),
.env = (call_env_parser_t[]) {
- { FR_CALL_ENV_OFFSET("key", FR_TYPE_STRING, 0, cache_call_env_t, key,
- NULL, T_INVALID, true, false, true) },
+ { FR_CALL_ENV_OFFSET("key", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT, cache_call_env_t, key) },
CALL_ENV_TERMINATOR
}
};
#include <freeradius-devel/server/base.h>
#include <freeradius-devel/server/password.h>
#include <freeradius-devel/server/module_rlm.h>
+#include <freeradius-devel/server/cf_parse.h>
#include <freeradius-devel/util/chap.h>
#include <freeradius-devel/unlang/xlat_func.h>
#include <freeradius-devel/unlang/call_env.h>
static const call_env_method_t chap_xlat_method_env = { \
FR_CALL_ENV_METHOD_OUT(chap_xlat_call_env_t),
.env = (call_env_parser_t[]){
- { FR_CALL_ENV_OFFSET("chap_challenge", FR_TYPE_OCTETS, CONF_FLAG_ATTRIBUTE, chap_xlat_call_env_t,
- chap_challenge, "&Chap-Challenge", T_BARE_WORD, true, true, true) },
+ { FR_CALL_ENV_OFFSET("chap_challenge", FR_TYPE_OCTETS,
+ CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT,
+ chap_xlat_call_env_t,
+ chap_challenge), .pair.dflt = "&Chap-Challenge", .pair.dflt_quote = T_BARE_WORD },
CALL_ENV_TERMINATOR
}
};
static const call_env_method_t chap_autz_method_env = { \
FR_CALL_ENV_METHOD_OUT(chap_autz_call_env_t),
.env = (call_env_parser_t[]){
- { FR_CALL_ENV_OFFSET("chap_password", FR_TYPE_OCTETS, CONF_FLAG_ATTRIBUTE, chap_autz_call_env_t,
- chap_password, "&Chap-Password", T_BARE_WORD, true, true, true) },
- { FR_CALL_ENV_TMPL_OFFSET("chap_challenge", FR_TYPE_OCTETS, CONF_FLAG_ATTRIBUTE, chap_autz_call_env_t,
- chap_challenge, chap_challenge_tmpl, "&Chap-Challenge", T_BARE_WORD, true, true, true) },
+ { FR_CALL_ENV_OFFSET("chap_password", FR_TYPE_OCTETS,
+ CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT,
+ chap_autz_call_env_t, chap_password),
+ .pair.dflt = "&Chap-Password", .pair.dflt_quote = T_BARE_WORD },
+ { FR_CALL_ENV_TMPL_OFFSET("chap_challenge", FR_TYPE_OCTETS,
+ CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT,
+ chap_autz_call_env_t, chap_challenge, chap_challenge_tmpl),
+ .pair.dflt = "&Chap-Challenge", .pair.dflt_quote = T_BARE_WORD },
CALL_ENV_TERMINATOR
}
};
static const call_env_method_t chap_auth_method_env = { \
FR_CALL_ENV_METHOD_OUT(chap_auth_call_env_t),
.env = (call_env_parser_t[]){
- { FR_CALL_ENV_OFFSET("username", FR_TYPE_STRING, CONF_FLAG_ATTRIBUTE, chap_auth_call_env_t,
- username, "&User-Name", T_BARE_WORD, true, false, true) },
- { FR_CALL_ENV_OFFSET("chap_password", FR_TYPE_OCTETS, CONF_FLAG_ATTRIBUTE, chap_auth_call_env_t,
- chap_password, "&Chap-Password", T_BARE_WORD, true, true, true) },
- { FR_CALL_ENV_OFFSET("chap_challenge", FR_TYPE_OCTETS, CONF_FLAG_ATTRIBUTE, chap_auth_call_env_t,
- chap_challenge, "&Chap-Challenge", T_BARE_WORD, true, true, true) },
+ { FR_CALL_ENV_OFFSET("username", FR_TYPE_STRING,
+ CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT,
+ chap_auth_call_env_t, username),
+ .pair.dflt = "&User-Name", .pair.dflt_quote = T_BARE_WORD },
+ { FR_CALL_ENV_OFFSET("chap_password", FR_TYPE_OCTETS,
+ CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT,
+ chap_auth_call_env_t, chap_password),
+ .pair.dflt = "&Chap-Password", .pair.dflt_quote = T_BARE_WORD },
+ { FR_CALL_ENV_OFFSET("chap_challenge", FR_TYPE_OCTETS,
+ CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT,
+ chap_auth_call_env_t, chap_challenge),
+ .pair.dflt = "&Chap-Challenge", .pair.dflt_quote = T_BARE_WORD },
CALL_ENV_TERMINATOR
}
};
#include <freeradius-devel/unlang/interpret.h>
#include <freeradius-devel/unlang/call_env.h>
#include <freeradius-devel/util/debug.h>
+#include <freeradius-devel/util/token.h>
#include <freeradius-devel/server/pairmove.h>
#include <freeradius-devel/unlang/xlat_func.h>
#include <freeradius-devel/unlang/xlat.h>
static const call_env_method_t exec_method_env = {
FR_CALL_ENV_METHOD_OUT(exec_call_env_t),
.env = (call_env_parser_t[]){
- { FR_CALL_ENV_TMPL_ONLY_OFFSET("program", FR_TYPE_STRING, 0, exec_call_env_t, program, NULL,
- T_BACK_QUOTED_STRING, false), .pair.force_quote = true },
+ { FR_CALL_ENV_TMPL_ONLY_OFFSET("program", FR_TYPE_STRING, CALL_ENV_FLAG_FORCE_QUOTE, exec_call_env_t, program), .pair.dflt_quote = T_BACK_QUOTED_STRING },
CALL_ENV_TERMINATOR
}
};
static const call_env_method_t method_env = {
FR_CALL_ENV_METHOD_OUT(rlm_files_env_t),
.env = (call_env_parser_t[]){
- { FR_CALL_ENV_OFFSET("key", FR_TYPE_VOID, 0, rlm_files_env_t, key, "%{%{Stripped-User-Name} || %{User-Name}}",
- T_DOUBLE_QUOTED_STRING, true, false, false) },
+ { FR_CALL_ENV_OFFSET("key", FR_TYPE_VOID, CALL_ENV_FLAG_REQUIRED, rlm_files_env_t, key),
+ .pair.dflt = "%{%{Stripped-User-Name} || %{User-Name}}", .pair.dflt_quote = T_DOUBLE_QUOTED_STRING },
CALL_ENV_TERMINATOR
},
};
} ldap_xlat_profile_call_env_t;
static const call_env_parser_t sasl_call_env[] = {
- { FR_CALL_ENV_OFFSET("mech", FR_TYPE_STRING, 0, ldap_auth_call_env_t, user_sasl_mech,
- NULL, T_INVALID, false, false, false) },
- { FR_CALL_ENV_OFFSET("authname", FR_TYPE_STRING, 0, ldap_auth_call_env_t, user_sasl_authname,
- NULL, T_INVALID, false, false, false) },
- { FR_CALL_ENV_OFFSET("proxy", FR_TYPE_STRING, 0, ldap_auth_call_env_t, user_sasl_proxy,
- NULL, T_INVALID, false, true, false) },
- { FR_CALL_ENV_OFFSET("realm", FR_TYPE_STRING, 0, ldap_auth_call_env_t, user_sasl_realm,
- NULL, T_INVALID, false, true, false) },
+ { FR_CALL_ENV_OFFSET("mech", FR_TYPE_STRING, CALL_ENV_FLAG_NONE, ldap_auth_call_env_t, user_sasl_mech) },
+ { FR_CALL_ENV_OFFSET("authname", FR_TYPE_STRING, CALL_ENV_FLAG_NONE, ldap_auth_call_env_t, user_sasl_authname) },
+ { FR_CALL_ENV_OFFSET("proxy", FR_TYPE_STRING, CALL_ENV_FLAG_NONE, ldap_auth_call_env_t, user_sasl_proxy) },
+ { FR_CALL_ENV_OFFSET("realm", FR_TYPE_STRING, CALL_ENV_FLAG_NONE, ldap_auth_call_env_t, user_sasl_realm) },
CALL_ENV_TERMINATOR
};
CONF_PARSER_TERMINATOR
};
-static const call_env_parser_t autz_profile_call_env[] = {
- { FR_CALL_ENV_OFFSET("default", FR_TYPE_STRING, 0, ldap_autz_call_env_t, default_profile,
- NULL, T_INVALID, false, false, true) },
- { FR_CALL_ENV_OFFSET("filter", FR_TYPE_STRING, 0, ldap_autz_call_env_t, profile_filter,
- "(&)", T_SINGLE_QUOTED_STRING, false, false, true ) }, //!< Correct filter for when the DN is known.
- CALL_ENV_TERMINATOR
-};
-
/*
* User configuration
*/
CONF_PARSER_TERMINATOR
};
-#define user_call_env(_prefix, _struct, ...) \
-static const call_env_parser_t _prefix ## _user_call_env[] = { \
- { FR_CALL_ENV_OFFSET("base_dn", FR_TYPE_STRING, 0, _struct, user_base, \
- "", T_SINGLE_QUOTED_STRING, true, false, true) }, \
- { FR_CALL_ENV_OFFSET("filter", FR_TYPE_STRING, 0, _struct, user_filter, \
- NULL, T_INVALID, false, true, true) }, \
- ##__VA_ARGS__, \
- CALL_ENV_TERMINATOR \
-}
-
-user_call_env(auth, ldap_auth_call_env_t, { FR_CALL_ENV_SUBSECTION("sasl", NULL, sasl_call_env, false) },
- { FR_CALL_ENV_TMPL_OFFSET("password_attribute", FR_TYPE_STRING, CONF_FLAG_ATTRIBUTE, ldap_auth_call_env_t, password,
- password_tmpl, "&User-Password", T_BARE_WORD, true, true, true) } );
-
-user_call_env(autz, ldap_autz_call_env_t);
-
-user_call_env(usermod, ldap_usermod_call_env_t);
-
-user_call_env(memberof, ldap_xlat_memberof_call_env_t);
-
/*
* Group configuration
*/
CONF_PARSER_TERMINATOR
};
-static const call_env_parser_t autz_group_call_env[] = {
- { FR_CALL_ENV_OFFSET("base_dn", FR_TYPE_STRING, 0, ldap_autz_call_env_t, group_base,
- NULL, T_INVALID, false, false, true) },
- CALL_ENV_TERMINATOR
-};
-
-static const call_env_parser_t memberof_group_call_env[] = {
- { FR_CALL_ENV_OFFSET("base_dn", FR_TYPE_STRING, 0, ldap_xlat_memberof_call_env_t, group_base,
- NULL, T_INVALID, false, false, true) },
- CALL_ENV_TERMINATOR
-};
-
/*
* Reference for accounting updates
*/
CONF_PARSER_TERMINATOR
};
+#define USER_CALL_ENV_COMMON(_struct) \
+ { FR_CALL_ENV_OFFSET("base_dn", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT, _struct, user_base), .pair.dflt = "", .pair.dflt_quote = T_SINGLE_QUOTED_STRING }, \
+ { FR_CALL_ENV_OFFSET("filter", FR_TYPE_STRING, CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT, _struct, user_filter), .pair.dflt = "(&)", .pair.dflt_quote = T_SINGLE_QUOTED_STRING }
+
static const call_env_method_t authenticate_method_env = {
FR_CALL_ENV_METHOD_OUT(ldap_auth_call_env_t),
.env = (call_env_parser_t[]) {
- { FR_CALL_ENV_SUBSECTION("user", NULL, auth_user_call_env, true) },
+ { FR_CALL_ENV_SUBSECTION("user", NULL, CALL_ENV_FLAG_REQUIRED,
+ ((call_env_parser_t[]) {
+ USER_CALL_ENV_COMMON(ldap_auth_call_env_t),
+ { FR_CALL_ENV_TMPL_OFFSET("password_attribute", FR_TYPE_STRING,
+ CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT,
+ ldap_auth_call_env_t, password, password_tmpl),
+ .pair.dflt = "&User-Password", .pair.dflt_quote = T_BARE_WORD },
+ { FR_CALL_ENV_SUBSECTION("sasl", NULL, CALL_ENV_FLAG_NONE, sasl_call_env) },
+ CALL_ENV_TERMINATOR
+ })) },
CALL_ENV_TERMINATOR
}
};
static const call_env_method_t authorize_method_env = {
FR_CALL_ENV_METHOD_OUT(ldap_autz_call_env_t),
.env = (call_env_parser_t[]) {
- { FR_CALL_ENV_SUBSECTION("user", NULL, autz_user_call_env, true) },
- { FR_CALL_ENV_SUBSECTION("group", NULL, autz_group_call_env, false) },
- { FR_CALL_ENV_SUBSECTION("profile", NULL, autz_profile_call_env, false) },
+ { FR_CALL_ENV_SUBSECTION("user", NULL, CALL_ENV_FLAG_REQUIRED,
+ ((call_env_parser_t[]) {
+ USER_CALL_ENV_COMMON(ldap_autz_call_env_t),
+ CALL_ENV_TERMINATOR
+ })) },
+ { FR_CALL_ENV_SUBSECTION("group", NULL, CALL_ENV_FLAG_NONE,
+ ((call_env_parser_t[]) {
+ { FR_CALL_ENV_OFFSET("base_dn", FR_TYPE_STRING, CALL_ENV_FLAG_CONCAT, ldap_autz_call_env_t, group_base) },
+ CALL_ENV_TERMINATOR
+ })) },
+ { FR_CALL_ENV_SUBSECTION("profile", NULL, CALL_ENV_FLAG_NONE,
+ ((call_env_parser_t[]) {
+ { FR_CALL_ENV_OFFSET("default", FR_TYPE_STRING, CALL_ENV_FLAG_CONCAT, ldap_autz_call_env_t, default_profile) },
+ { FR_CALL_ENV_OFFSET("filter", FR_TYPE_STRING, CALL_ENV_FLAG_CONCAT, ldap_autz_call_env_t, profile_filter),
+ .pair.dflt = "(&)", .pair.dflt_quote = T_SINGLE_QUOTED_STRING }, //!< Correct filter for when the DN is known.
+ CALL_ENV_TERMINATOR
+ } )) },
CALL_ENV_TERMINATOR
}
};
static const call_env_method_t usermod_method_env = {
FR_CALL_ENV_METHOD_OUT(ldap_usermod_call_env_t),
.env = (call_env_parser_t[]) {
- { FR_CALL_ENV_SUBSECTION("user", NULL, usermod_user_call_env, true) },
+ { FR_CALL_ENV_SUBSECTION("user", NULL, CALL_ENV_FLAG_REQUIRED,
+ ((call_env_parser_t[]) {
+ USER_CALL_ENV_COMMON(ldap_usermod_call_env_t),
+ CALL_ENV_TERMINATOR
+ })) },
+
CALL_ENV_TERMINATOR
}
};
static const call_env_method_t xlat_memberof_method_env = {
FR_CALL_ENV_METHOD_OUT(ldap_xlat_memberof_call_env_t),
.env = (call_env_parser_t[]) {
- { FR_CALL_ENV_SUBSECTION("user", NULL, memberof_user_call_env, true) },
- { FR_CALL_ENV_SUBSECTION("group", NULL, memberof_group_call_env, false) },
+ { FR_CALL_ENV_SUBSECTION("user", NULL, CALL_ENV_FLAG_REQUIRED,
+ ((call_env_parser_t[]) {
+ USER_CALL_ENV_COMMON(ldap_xlat_memberof_call_env_t),
+ CALL_ENV_TERMINATOR
+ })) },
+ { FR_CALL_ENV_SUBSECTION("group", NULL, CALL_ENV_FLAG_NONE,
+ ((call_env_parser_t[]) {
+ { FR_CALL_ENV_OFFSET("base_dn", FR_TYPE_STRING, CALL_ENV_FLAG_CONCAT, ldap_xlat_memberof_call_env_t, group_base) },
+ CALL_ENV_TERMINATOR
+ })) },
CALL_ENV_TERMINATOR
}
};
static const call_env_method_t xlat_profile_method_env = {
FR_CALL_ENV_METHOD_OUT(ldap_xlat_profile_call_env_t),
.env = (call_env_parser_t[]) {
- { FR_CALL_ENV_SUBSECTION("profile", NULL,
+ { FR_CALL_ENV_SUBSECTION("profile", NULL, CALL_ENV_FLAG_NONE,
((call_env_parser_t[]) {
- { FR_CALL_ENV_OFFSET("filter", FR_TYPE_STRING, 0, ldap_xlat_profile_call_env_t, profile_filter,
- "(&)", T_SINGLE_QUOTED_STRING, false, false, true ) }, //!< Correct filter for when the DN is known.
+ { FR_CALL_ENV_OFFSET("filter", FR_TYPE_STRING, CALL_ENV_FLAG_CONCAT, ldap_xlat_profile_call_env_t, profile_filter),
+ .pair.dflt = "(&)", .pair.dflt_quote = T_SINGLE_QUOTED_STRING }, //!< Correct filter for when the DN is known.
CALL_ENV_TERMINATOR
- }),
- false) },
+ })) },
CALL_ENV_TERMINATOR
}
};
static const call_env_method_t mschap_ ## _x ## _method_env = { \
FR_CALL_ENV_METHOD_OUT(mschap_ ## _x ## _call_env_t), \
.env = (call_env_parser_t[]){ \
- { FR_CALL_ENV_SUBSECTION("attributes", NULL, _x ## _call_env, true) }, \
+ { FR_CALL_ENV_SUBSECTION("attributes", NULL, CALL_ENV_FLAG_REQUIRED, _x ## _call_env) }, \
CALL_ENV_TERMINATOR \
} \
}
#define MSCHAP_COMMON_CALL_ENV(_x) \
-{ FR_CALL_ENV_TMPL_ONLY_OFFSET("chap_challenge", FR_TYPE_OCTETS, CONF_FLAG_ATTRIBUTE, mschap_ ## _x ## _call_env_t, \
- chap_challenge, "&Vendor-Specific.Microsoft.CHAP-Challenge", T_BARE_WORD, true) }, \
-{ FR_CALL_ENV_TMPL_ONLY_OFFSET("chap_response", FR_TYPE_OCTETS, CONF_FLAG_ATTRIBUTE, mschap_ ## _x ## _call_env_t, \
- chap_response, "&Vendor-Specific.Microsoft.CHAP-Response", T_BARE_WORD, true) }, \
-{ FR_CALL_ENV_TMPL_ONLY_OFFSET("chap2_response", FR_TYPE_OCTETS, CONF_FLAG_ATTRIBUTE, mschap_ ## _x ## _call_env_t, \
- chap2_response, "&Vendor-Specific.Microsoft.CHAP2-Response", T_BARE_WORD, true) }
+{ FR_CALL_ENV_TMPL_ONLY_OFFSET("chap_challenge", FR_TYPE_OCTETS, CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED, mschap_ ## _x ## _call_env_t, chap_challenge), \
+ .pair.dflt = "&Vendor-Specific.Microsoft.CHAP-Challenge", .pair.dflt_quote = T_BARE_WORD }, \
+{ FR_CALL_ENV_TMPL_ONLY_OFFSET("chap_response", FR_TYPE_OCTETS, CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED, mschap_ ## _x ## _call_env_t, chap_response), \
+ .pair.dflt = "&Vendor-Specific.Microsoft.CHAP-Response", .pair.dflt_quote = T_BARE_WORD }, \
+{ FR_CALL_ENV_TMPL_ONLY_OFFSET("chap2_response", FR_TYPE_OCTETS, CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED, mschap_ ## _x ## _call_env_t, chap2_response), \
+ .pair.dflt = "&Vendor-Specific.Microsoft.CHAP2-Response", .pair.dflt_quote = T_BARE_WORD }
#define MSCHAP_OPT_CALL_ENV(_opt, _x) \
-{ FR_CALL_ENV_TMPL_ONLY_OFFSET(STRINGIFY(_opt), FR_TYPE_OCTETS, CONF_FLAG_ATTRIBUTE, mschap_ ## _x ## _call_env_t, \
- _opt, NULL, T_INVALID, false) }
+{ FR_CALL_ENV_TMPL_ONLY_OFFSET(STRINGIFY(_opt), FR_TYPE_OCTETS, CALL_ENV_FLAG_ATTRIBUTE, mschap_ ## _x ## _call_env_t, _opt) }
typedef struct {
tmpl_t const *username;
} mschap_xlat_call_env_t;
static const call_env_parser_t xlat_call_env[] = {
- { FR_CALL_ENV_TMPL_ONLY_OFFSET("username", FR_TYPE_STRING, CONF_FLAG_ATTRIBUTE, mschap_xlat_call_env_t,
- username, "&User-Name", T_BARE_WORD, true) },
+ { FR_CALL_ENV_TMPL_ONLY_OFFSET("username", FR_TYPE_STRING, CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED, mschap_xlat_call_env_t, username), .pair.dflt = "&User-Name", .pair.dflt_quote = T_BARE_WORD },
MSCHAP_COMMON_CALL_ENV(xlat),
CALL_ENV_TERMINATOR
};
MSCHAP_CALL_ENV(xlat);
static const call_env_parser_t auth_call_env[] = {
- { FR_CALL_ENV_TMPL_ONLY_OFFSET("username", FR_TYPE_STRING, CONF_FLAG_ATTRIBUTE, mschap_auth_call_env_t,
- username, "&User-Name", T_BARE_WORD, true) },
+ { FR_CALL_ENV_TMPL_ONLY_OFFSET("username", FR_TYPE_STRING, CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED, mschap_auth_call_env_t, username), .pair.dflt = "&User-Name", .pair.dflt_quote = T_BARE_WORD },
MSCHAP_COMMON_CALL_ENV(auth),
MSCHAP_OPT_CALL_ENV(chap2_success, auth),
MSCHAP_OPT_CALL_ENV(chap_mppe_keys, auth),
.inst_size = sizeof(pap_call_env_t),
.inst_type = "pap_call_env_t",
.env = (call_env_parser_t[]) {
- { FR_CALL_ENV_TMPL_OFFSET("password_attribute", FR_TYPE_STRING, CONF_FLAG_ATTRIBUTE, pap_call_env_t, password,
- password_tmpl, "&User-Password", T_BARE_WORD, true, true, true) },
+ { FR_CALL_ENV_TMPL_OFFSET("password_attribute", FR_TYPE_STRING,
+ CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT,
+ pap_call_env_t, password, password_tmpl), .pair.dflt = "&User-Password", .pair.dflt_quote = T_BARE_WORD },
CALL_ENV_TERMINATOR
}
};
#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/util/base16.h>
+#include <freeradius-devel/util/token.h>
#include <freeradius-devel/redis/base.h>
#include <freeradius-devel/redis/cluster.h>
static const call_env_method_t redis_ippool_alloc_method_env = {
FR_CALL_ENV_METHOD_OUT(redis_ippool_alloc_call_env_t),
.env = (call_env_parser_t[]){
- { FR_CALL_ENV_OFFSET("pool_name", FR_TYPE_STRING, 0, redis_ippool_alloc_call_env_t, pool_name,
- NULL, T_INVALID, true, false, true) },
- { FR_CALL_ENV_OFFSET("owner", FR_TYPE_STRING, 0, redis_ippool_alloc_call_env_t, owner,
- NULL, T_INVALID, true, false, true) },
- { FR_CALL_ENV_OFFSET("gateway", FR_TYPE_STRING, 0, redis_ippool_alloc_call_env_t, gateway_id,
- "", T_SINGLE_QUOTED_STRING, false, true, true ) },
- { FR_CALL_ENV_OFFSET("offer_time", FR_TYPE_UINT32, 0, redis_ippool_alloc_call_env_t, offer_time,
- NULL, T_INVALID, false, false, false) },
- { FR_CALL_ENV_OFFSET("lease_time", FR_TYPE_UINT32, 0, redis_ippool_alloc_call_env_t, lease_time,
- NULL, T_INVALID, true, false, false) },
- { FR_CALL_ENV_OFFSET("requested_address", FR_TYPE_STRING, 0, redis_ippool_alloc_call_env_t, requested_address,
- "%{%{Requested-IP-Address} || %{Net.Src.IP}}", T_DOUBLE_QUOTED_STRING,
- true, true, false) },
- { FR_CALL_ENV_TMPL_ONLY_OFFSET("allocated_address_attr", 0, CONF_FLAG_ATTRIBUTE, redis_ippool_alloc_call_env_t,
- allocated_address_attr, NULL, T_INVALID, true ) },
- { FR_CALL_ENV_TMPL_ONLY_OFFSET("range_attr", 0, CONF_FLAG_ATTRIBUTe, redis_ippool_alloc_call_env_t,
- range_attr, "&reply.IP-Pool.Range", T_BARE_WORD, true) },
- { FR_CALL_ENV_TMPL_ONLY_OFFSET("expiry_attr", 0, CONF_FLAG_ATTRIBUTE, redis_ippool_alloc_call_env_t,
- expiry_attr, NULL, T_INVALID, false) },
+ { FR_CALL_ENV_OFFSET("pool_name", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT,
+ redis_ippool_alloc_call_env_t, pool_name) },
+ { FR_CALL_ENV_OFFSET("owner", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT,
+ redis_ippool_alloc_call_env_t, owner) },
+ { FR_CALL_ENV_OFFSET("gateway", FR_TYPE_STRING, CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT,
+ redis_ippool_alloc_call_env_t, gateway_id ), .pair.dflt = "", .pair.dflt_quote = T_SINGLE_QUOTED_STRING },
+ { FR_CALL_ENV_OFFSET("offer_time", FR_TYPE_UINT32, CALL_ENV_FLAG_NONE, redis_ippool_alloc_call_env_t, offer_time ) },
+ { FR_CALL_ENV_OFFSET("lease_time", FR_TYPE_UINT32, CALL_ENV_FLAG_REQUIRED, redis_ippool_alloc_call_env_t, lease_time) },
+ { FR_CALL_ENV_OFFSET("requested_address", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_NULLABLE, redis_ippool_alloc_call_env_t, requested_address ),
+ .pair.dflt = "%{%{Requested-IP-Address} || %{Net.Src.IP}}", .pair.dflt_quote = T_DOUBLE_QUOTED_STRING },
+ { FR_CALL_ENV_TMPL_ONLY_OFFSET("allocated_address_attr", FR_TYPE_VOID, CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED, redis_ippool_alloc_call_env_t, allocated_address_attr) },
+ { FR_CALL_ENV_TMPL_ONLY_OFFSET("range_attr", FR_TYPE_VOID, CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED, redis_ippool_alloc_call_env_t, range_attr),
+ .pair.dflt = "&reply.IP-Pool.Range", .pair.dflt_quote = T_BARE_WORD },
+ { FR_CALL_ENV_TMPL_ONLY_OFFSET("expiry_attr", FR_TYPE_VOID, CALL_ENV_FLAG_ATTRIBUTE, redis_ippool_alloc_call_env_t, expiry_attr) },
CALL_ENV_TERMINATOR
}
};
static const call_env_method_t redis_ippool_update_method_env = {
FR_CALL_ENV_METHOD_OUT(redis_ippool_update_call_env_t),
.env = (call_env_parser_t[]) {
- { FR_CALL_ENV_OFFSET("pool_name", FR_TYPE_STRING, 0, redis_ippool_update_call_env_t, pool_name,
- NULL, T_INVALID, true, false, true) },
- { FR_CALL_ENV_OFFSET("owner", FR_TYPE_STRING, 0, redis_ippool_update_call_env_t, owner,
- NULL, T_INVALID, true, false, true) },
- { FR_CALL_ENV_OFFSET("gateway", FR_TYPE_STRING, 0, redis_ippool_update_call_env_t, gateway_id,
- "", T_SINGLE_QUOTED_STRING, false, true, true ) },
- { FR_CALL_ENV_OFFSET("lease_time", FR_TYPE_UINT32, 0, redis_ippool_update_call_env_t, lease_time,
- NULL, T_INVALID, true, false, false) },
- { FR_CALL_ENV_OFFSET("requested_address", FR_TYPE_STRING, 0, redis_ippool_update_call_env_t, requested_address,
- "%{%{Requested-IP-Address} || %{Net.Src.IP}}", T_DOUBLE_QUOTED_STRING,
- true, true, false) },
- { FR_CALL_ENV_TMPL_ONLY_OFFSET("allocated_address_attr", 0, CONF_FLAG_ATTRIBUTE, redis_ippool_update_call_env_t,
- allocated_address_attr, NULL, T_INVALID, true ) },
- { FR_CALL_ENV_TMPL_ONLY_OFFSET("range_attr", 0, CONF_FLAG_ATTRIBUTE, redis_ippool_update_call_env_t,
- range_attr, "&reply.IP-Pool.Range", T_BARE_WORD, true) },
- { FR_CALL_ENV_TMPL_ONLY_OFFSET("expiry_attr", 0, CONF_FLAG_ATTRIBUTE, redis_ippool_update_call_env_t,
- expiry_attr, NULL, T_INVALID, false) },
+ { FR_CALL_ENV_OFFSET("pool_name", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT, redis_ippool_update_call_env_t, pool_name) },
+ { FR_CALL_ENV_OFFSET("owner", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT, redis_ippool_update_call_env_t, owner) },
+ { FR_CALL_ENV_OFFSET("gateway", FR_TYPE_STRING, CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT, redis_ippool_update_call_env_t, gateway_id),
+ .pair.dflt = "", .pair.dflt_quote = T_SINGLE_QUOTED_STRING },
+ { FR_CALL_ENV_OFFSET("lease_time", FR_TYPE_UINT32, CALL_ENV_FLAG_REQUIRED, redis_ippool_update_call_env_t, lease_time) },
+ { FR_CALL_ENV_OFFSET("requested_address", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_NULLABLE, redis_ippool_update_call_env_t, requested_address),
+ .pair.dflt = "%{%{Requested-IP-Address} || %{Net.Src.IP}}", .pair.dflt_quote = T_DOUBLE_QUOTED_STRING },
+ { FR_CALL_ENV_TMPL_ONLY_OFFSET("allocated_address_attr", FR_TYPE_VOID, CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED, redis_ippool_update_call_env_t, allocated_address_attr) },
+ { FR_CALL_ENV_TMPL_ONLY_OFFSET("range_attr", FR_TYPE_VOID, CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED, redis_ippool_update_call_env_t, range_attr),
+ .pair.dflt = "&reply.IP-Pool.Range", .pair.dflt_quote = T_BARE_WORD },
+ { FR_CALL_ENV_TMPL_ONLY_OFFSET("expiry_attr", FR_TYPE_VOID, CALL_ENV_FLAG_ATTRIBUTE, redis_ippool_update_call_env_t, expiry_attr) },
CALL_ENV_TERMINATOR
}
};
static const call_env_method_t redis_ippool_release_method_env = {
FR_CALL_ENV_METHOD_OUT(redis_ippool_release_call_env_t),
.env = (call_env_parser_t[]) {
- { FR_CALL_ENV_OFFSET("pool_name", FR_TYPE_STRING, 0, redis_ippool_release_call_env_t, pool_name,
- NULL, T_INVALID, true, false, true) },
- { FR_CALL_ENV_OFFSET("owner", FR_TYPE_STRING, 0, redis_ippool_release_call_env_t, owner,
- NULL, T_INVALID, true, false, true) },
- { FR_CALL_ENV_OFFSET("gateway", FR_TYPE_STRING, 0, redis_ippool_release_call_env_t, gateway_id,
- "", T_SINGLE_QUOTED_STRING, false, true, true ) },
- { FR_CALL_ENV_OFFSET("requested_address", FR_TYPE_STRING, 0, redis_ippool_release_call_env_t, requested_address,
- "%{%{Requested-IP-Address} || %{Net.Src.IP}}", T_DOUBLE_QUOTED_STRING,
- true, true, false) },
+ { FR_CALL_ENV_OFFSET("pool_name", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT, redis_ippool_release_call_env_t, pool_name) },
+ { FR_CALL_ENV_OFFSET("owner", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT, redis_ippool_release_call_env_t, owner) },
+ { FR_CALL_ENV_OFFSET("gateway", FR_TYPE_STRING, CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT, redis_ippool_release_call_env_t, gateway_id),
+ .pair.dflt = "", .pair.dflt_quote = T_SINGLE_QUOTED_STRING },
+ { FR_CALL_ENV_OFFSET("requested_address", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_NULLABLE, redis_ippool_release_call_env_t, requested_address),
+ .pair.dflt = "%{%{Requested-IP-Address} || %{Net.Src.IP}}", .pair.dflt_quote = T_DOUBLE_QUOTED_STRING },
CALL_ENV_TERMINATOR
}
};
static const call_env_method_t redis_ippool_bulk_release_method_env = {
FR_CALL_ENV_METHOD_OUT(redis_ippool_bulk_release_call_env_t),
.env = (call_env_parser_t[]) {
- { FR_CALL_ENV_OFFSET("pool_name", FR_TYPE_STRING, 0, redis_ippool_bulk_release_call_env_t, pool_name,
- NULL, T_INVALID, true, false, true) },
- { FR_CALL_ENV_OFFSET("gateway", FR_TYPE_STRING, 0, redis_ippool_bulk_release_call_env_t, gateway_id,
- "", T_SINGLE_QUOTED_STRING, false, true, true ) },
+ { FR_CALL_ENV_OFFSET("pool_name", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT, redis_ippool_bulk_release_call_env_t, pool_name) },
+ { FR_CALL_ENV_OFFSET("gateway", FR_TYPE_STRING, CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT, redis_ippool_bulk_release_call_env_t, gateway_id),
+ .pair.dflt = "", .pair.dflt_quote = T_SINGLE_QUOTED_STRING },
CALL_ENV_TERMINATOR
}
};
static conf_parser_t section_config[] = {
{ FR_CONF_OFFSET_FLAGS("insert", CONF_FLAG_REQUIRED | CONF_FLAG_XLAT, rlm_rediswho_t, insert) },
{ FR_CONF_OFFSET_FLAGS("trim", CONF_FLAG_XLAT, rlm_rediswho_t, trim) }, /* required only if trim_count > 0 */
- { FR_CONF_OFFSET_FLAGS("expire", CONF_FLAG_REQUIRED | CONF_FLAG_XLAT, rlm_rediswho_t, expire) },
+ { FR_CONF_OFFSET_FLAGS("expire", CONF_FLAG_REQUIRED, rlm_rediswho_t, expire) },
CONF_PARSER_TERMINATOR
};
#include <freeradius-devel/server/module_rlm.h>
#include <freeradius-devel/server/tmpl_dcursor.h>
#include <freeradius-devel/util/slab.h>
+#include <freeradius-devel/util/token.h>
#include <freeradius-devel/unlang/call_env.h>
static const call_env_method_t method_env = {
FR_CALL_ENV_METHOD_OUT(rlm_smtp_env_t),
.env = (call_env_parser_t[]) {
- { FR_CALL_ENV_TMPL_OFFSET("username", FR_TYPE_STRING, 0, rlm_smtp_env_t, username, username_tmpl, NULL,
- T_DOUBLE_QUOTED_STRING, false, true, true) },
- { FR_CALL_ENV_OFFSET("password", FR_TYPE_STRING, 0, rlm_smtp_env_t, password, NULL,
- T_DOUBLE_QUOTED_STRING, false, true, true) },
+ { FR_CALL_ENV_TMPL_OFFSET("username", FR_TYPE_STRING, CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT, rlm_smtp_env_t, username, username_tmpl),
+ .pair.dflt_quote = T_DOUBLE_QUOTED_STRING },
+ { FR_CALL_ENV_OFFSET("password", FR_TYPE_STRING, CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT, rlm_smtp_env_t, password), .pair.dflt_quote = T_DOUBLE_QUOTED_STRING },
CALL_ENV_TERMINATOR
}
};
static const call_env_method_t method_env = {
FR_CALL_ENV_METHOD_OUT(rlm_totp_call_env_t),
.env = (call_env_parser_t[]) {
- { FR_CALL_ENV_OFFSET("secret", FR_TYPE_STRING, 0, rlm_totp_call_env_t, secret,
- "&control.TOTP.Secret", T_BARE_WORD, false, true, false) },
+ { FR_CALL_ENV_OFFSET("secret", FR_TYPE_STRING, CALL_ENV_FLAG_NULLABLE, rlm_totp_call_env_t, secret),
+ .pair.dflt = "&control.TOTP.Secret", .pair.dflt_quote = T_BARE_WORD },
- { FR_CALL_ENV_OFFSET("key", FR_TYPE_STRING, 0, rlm_totp_call_env_t, key,
- "&control.TOTP.key", T_BARE_WORD, false, true, false) },
+ { FR_CALL_ENV_OFFSET("key", FR_TYPE_STRING, CALL_ENV_FLAG_NULLABLE, rlm_totp_call_env_t, key),
+ .pair.dflt = "&control.TOTP.key", .pair.dflt_quote = T_BARE_WORD },
- { FR_CALL_ENV_OFFSET("user_password", FR_TYPE_STRING, 0, rlm_totp_call_env_t, user_password,
- "&request.TOTP.From-User", T_BARE_WORD, false, true, false) },
+ { FR_CALL_ENV_OFFSET("user_password", FR_TYPE_STRING, CALL_ENV_FLAG_NULLABLE, rlm_totp_call_env_t, user_password),
+ .pair.dflt = "&request.TOTP.From-User", .pair.dflt_quote = T_BARE_WORD },
CALL_ENV_TERMINATOR
}