]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
rearrange call env structures to make them more like conf_parser_t
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 24 Nov 2023 20:08:02 +0000 (14:08 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sat, 25 Nov 2023 01:11:33 +0000 (19:11 -0600)
13 files changed:
src/lib/unlang/call_env.c
src/lib/unlang/call_env.h
src/modules/rlm_cache/rlm_cache.c
src/modules/rlm_chap/rlm_chap.c
src/modules/rlm_exec/rlm_exec.c
src/modules/rlm_files/rlm_files.c
src/modules/rlm_ldap/rlm_ldap.c
src/modules/rlm_mschap/rlm_mschap.c
src/modules/rlm_pap/rlm_pap.c
src/modules/rlm_redis_ippool/rlm_redis_ippool.c
src/modules/rlm_rediswho/rlm_rediswho.c
src/modules/rlm_smtp/rlm_smtp.c
src/modules/rlm_totp/rlm_totp.c

index 952ad1498bd3f728f1be1565e25fa92b6a628d54..c8d8e0b8737baa7e50eb1fb6bb2804879d9d3599 100644 (file)
@@ -46,7 +46,7 @@ call_env_result_t call_env_value_parse(TALLOC_CTX *ctx, request_t *request, void
 
        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;
                }
@@ -56,14 +56,14 @@ call_env_result_t call_env_value_parse(TALLOC_CTX *ctx, request_t *request, void
        /*
         *      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;
@@ -121,7 +121,7 @@ static unlang_action_t call_env_expand_start(UNUSED rlm_rcode_t *p_result, UNUSE
                /*
                 *      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;
        }
 
@@ -137,8 +137,8 @@ static unlang_action_t call_env_expand_start(UNUSED rlm_rcode_t *p_result, UNUSE
        /*
         *      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.
@@ -177,19 +177,19 @@ static unlang_action_t call_env_expand_repeat(UNUSED rlm_rcode_t *p_result, UNUS
        /*
         *      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) {
@@ -257,11 +257,11 @@ static int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char
        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;
                        }
@@ -272,8 +272,8 @@ static int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char
 
                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;
@@ -283,7 +283,7 @@ static int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char
                 *      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;
                }
@@ -301,14 +301,14 @@ static int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char
                        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),
@@ -330,7 +330,7 @@ static int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char
                        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>"));
@@ -375,7 +375,7 @@ static size_t call_env_count(size_t *names_len, CONF_SECTION const *cs, call_env
        *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;
@@ -389,9 +389,9 @@ static size_t call_env_count(size_t *names_len, CONF_SECTION const *cs, call_env
                        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:
index 910258463b657ff11974d307956be20515cd79c4..5107dd349c99f3bbac696f952ab60a4f2ffd7fd3 100644 (file)
@@ -54,7 +54,59 @@ typedef enum {
        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
  *
@@ -65,37 +117,29 @@ typedef enum {
  * 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;
        };
 };
@@ -137,20 +181,20 @@ struct call_env_s {
  */
 #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.
@@ -186,64 +230,57 @@ _Generic((((_s *)NULL)->_f), \
        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);
index 9b8109ece15fb1b09682840a732d429374b28283..6793f11d674f730df22135d2e27a6e262813fa8d 100644 (file)
@@ -57,8 +57,7 @@ typedef struct {
 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
        }
 };
index 3aee2541a14de0df8911133fe7111120bb5738bb..1c929626c74de45f4cc859455625924bbc7a257a 100644 (file)
@@ -28,6 +28,7 @@ RCSID("$Id$")
 #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>
@@ -49,8 +50,10 @@ typedef struct {
 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
        }
 };
@@ -64,10 +67,14 @@ typedef struct {
 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
        }
 };
@@ -81,12 +88,18 @@ typedef struct {
 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
        }
 };
index 7a3406c31dccdf13b13c5f926dec5da28767ff27..81c9fd92d78233c84ab248ace2469852055c3cd2 100644 (file)
@@ -36,6 +36,7 @@ RCSID("$Id$")
 #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>
@@ -71,8 +72,7 @@ typedef struct {
 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
        }
 };
index 0eae40c53c07c8bdf758911a5c7552e36cb8c0b8..d6187fd0f6df6dcaf00acdd9ccd4ffee9a5da436 100644 (file)
@@ -709,8 +709,8 @@ static unlang_action_t CC_HINT(nonnull) mod_post_auth(rlm_rcode_t *p_result, mod
 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
        },
 };
index 311350ae6476f15075d7ada91f01e8f266d0d8f2..386f2d1f71defa3451dd49d991ededb453fdc633 100644 (file)
@@ -71,14 +71,10 @@ typedef struct {
 } 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
 };
 
@@ -90,14 +86,6 @@ static conf_parser_t profile_config[] = {
        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
  */
@@ -113,26 +101,6 @@ static conf_parser_t user_config[] = {
        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
  */
@@ -152,18 +120,6 @@ static conf_parser_t group_config[] = {
        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
  */
@@ -213,10 +169,23 @@ static const conf_parser_t module_config[] = {
        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
        }
 };
@@ -224,9 +193,23 @@ static const call_env_method_t authenticate_method_env = {
 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
        }
 };
@@ -234,7 +217,12 @@ static const call_env_method_t authorize_method_env = {
 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
        }
 };
@@ -242,8 +230,16 @@ static const call_env_method_t usermod_method_env = {
 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
        }
 };
@@ -251,13 +247,12 @@ static const call_env_method_t xlat_memberof_method_env = {
 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
        }
 };
index b3c0d6397fa2b20fa1f15d0433f7c7c5d90f67ef..9691ec7e9af8e572131da9246ea4c245b0bcfcce 100644 (file)
@@ -137,22 +137,21 @@ static const conf_parser_t module_config[] = {
 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;
@@ -162,8 +161,7 @@ typedef struct {
 } 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
 };
@@ -171,8 +169,7 @@ static const call_env_parser_t xlat_call_env[] = {
 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),
index 4bae376b19dcb62176d15efd0282cd9b11354874..215d815d0073599aabb50f5ccabde9958141a821 100644 (file)
@@ -91,8 +91,9 @@ static const call_env_method_t pap_method_env = {
        .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
        }
 };
index 65f77d15a5076b1804305b153a520e9dadcdfeeb..ac864315a6eda02ba86767bcbaa2fa994a382966 100644 (file)
@@ -46,6 +46,7 @@ RCSID("$Id$")
 
 #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>
@@ -183,25 +184,20 @@ typedef struct {
 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
        }
 };
@@ -209,23 +205,17 @@ static const call_env_method_t redis_ippool_alloc_method_env = {
 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
        }
 };
@@ -233,15 +223,12 @@ static const call_env_method_t redis_ippool_update_method_env = {
 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
        }
 };
@@ -249,10 +236,9 @@ static const call_env_method_t redis_ippool_release_method_env = {
 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
        }
 };
index 4cf7443155ba165b0a48b57650e0488cfbffc6b9..ce1b90f83201620fa354f4ee2db9208dc4046b9e 100644 (file)
@@ -54,7 +54,7 @@ typedef struct {
 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
 };
 
index 9777063954c24579e4e426d3dd7bf385ce820536..18b862d2327aebdbb89fa4b561154b0ca5f0a200 100644 (file)
@@ -31,6 +31,7 @@ RCSID("$Id$")
 #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>
 
@@ -1180,10 +1181,9 @@ static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
 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
        }
 };
index 029de4dd24b7e4b08c45737170eab63cb7e87250..b01bfcbe52ebbb6a0030ff216d478219b30c5c88 100644 (file)
@@ -42,14 +42,14 @@ typedef struct {
 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
        }