]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add tmpl only call environment entries
authorNick Porter <nick@portercomputing.co.uk>
Wed, 7 Jun 2023 13:44:24 +0000 (14:44 +0100)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 8 Jun 2023 18:57:03 +0000 (14:57 -0400)
For use where the requirement is just a tmpl to produce output pair(s)

src/lib/unlang/call_env.c
src/lib/unlang/call_env.h

index 1be1f439add6de3d89c53ff91c391d43c9fbf619..610c3a18dd877b7a21b9fcb1eaede01ed2070e8d 100644 (file)
@@ -90,6 +90,7 @@ int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char const *
                        call_env_parsed->rule = call_env;
                        call_env_parsed->opt_count = opt_count;
                        call_env_parsed->multi_index = multi_index;
+                       if (call_env->pair.type == CALL_ENV_TYPE_TMPL_ONLY) call_env_parsed->tmpl_only = true;
 
                        if (cp) {
                                value = cf_pair_value(cp);
@@ -187,8 +188,12 @@ static inline CC_HINT(always_inline) int call_env_value_parse(TALLOC_CTX *ctx, r
                                                              void **tmpl_out, call_env_parsed_t const *env,
                                                              fr_value_box_list_t *tmpl_expanded)
 {
-       fr_value_box_t  *vb = fr_value_box_list_head(tmpl_expanded);
+       fr_value_box_t  *vb;
 
+       if (tmpl_out) *tmpl_out = env->tmpl;
+       if (env->tmpl_only) return 0;
+
+       vb = fr_value_box_list_head(tmpl_expanded);
        if (!vb) {
                if (!env->rule->pair.nullable) {
                        RPEDEBUG("Failed to evaluate required module option %s", env->rule->name);
@@ -223,11 +228,13 @@ static inline CC_HINT(always_inline) int call_env_value_parse(TALLOC_CTX *ctx, r
                        if (!fr_value_box_list_initialised((fr_value_box_list_t *)out)) fr_value_box_list_init((fr_value_box_list_t *)out);
                        fr_value_box_list_insert_tail((fr_value_box_list_t *)out, vb);
                        break;
+
+               case CALL_ENV_TYPE_TMPL_ONLY:
+                       fr_assert(0);
+                       break;
                }
        }
 
-       if (tmpl_out) *tmpl_out = env->tmpl;
-
        return 0;
 }
 
@@ -241,6 +248,8 @@ typedef struct {
        void                            **env_data;             //!< Final destination structure for value boxes.
 } call_env_ctx_t;
 
+static unlang_action_t call_env_expand_repeat(rlm_rcode_t *p_result, int *priority, request_t *request, void *uctx);
+
 /** Start the expansion of a call environment tmpl.
  *
  */
@@ -257,6 +266,14 @@ static unlang_action_t call_env_expand_start(UNUSED rlm_rcode_t *p_result, UNUSE
        ctx = *call_env_ctx->env_data;
        env = call_env_ctx->last_expanded;
 
+       /*
+        *      If we only need the tmpl, use the repeat function to set the pointer.
+        */
+       if (env->tmpl_only) {
+               if (unlang_function_repeat_set(request, call_env_expand_repeat) < 0) return UNLANG_ACTION_FAIL;
+               return UNLANG_ACTION_CALCULATE_RESULT;
+       }
+
        /*
         *      Multi pair options should allocate boxes in the context of the array
         */
@@ -288,13 +305,14 @@ static unlang_action_t call_env_expand_start(UNUSED rlm_rcode_t *p_result, UNUSE
 static unlang_action_t call_env_expand_repeat(UNUSED rlm_rcode_t *p_result, UNUSED int *priority,
                                              request_t *request, void *uctx)
 {
-       void                    *out, *tmpl_out = NULL;
+       void                    *out = NULL, *tmpl_out = NULL;
        call_env_ctx_t          *call_env_ctx = talloc_get_type_abort(uctx, call_env_ctx_t);
        call_env_parsed_t       const *env;
 
        env = call_env_ctx->last_expanded;
        if (!env) return UNLANG_ACTION_CALCULATE_RESULT;
 
+       if (env->tmpl_only) goto tmpl_only;
        /*
         *      Find the location of the output
         */
@@ -309,6 +327,7 @@ static unlang_action_t call_env_expand_repeat(UNUSED rlm_rcode_t *p_result, UNUS
                out = ((uint8_t *)array) + env->rule->pair.size * env->multi_index;
        }
 
+tmpl_only:
        if (env->rule->pair.tmpl_offset) tmpl_out = ((uint8_t *)*call_env_ctx->env_data) + env->rule->pair.tmpl_offset;
 
        if (call_env_value_parse(*call_env_ctx->env_data, request, out, tmpl_out, env,
index 1ca2acdac2c24074194d5c9f21700df042e77551..3051d74399f51f0e94cd3c965dba1d9155668196 100644 (file)
@@ -41,7 +41,8 @@ FR_DLIST_TYPEDEFS(call_env_parsed, call_env_parsed_head_t, call_env_parsed_entry
 
 typedef enum {
        CALL_ENV_TYPE_VALUE_BOX = 1,
-       CALL_ENV_TYPE_VALUE_BOX_LIST
+       CALL_ENV_TYPE_VALUE_BOX_LIST,
+       CALL_ENV_TYPE_TMPL_ONLY
 } call_env_dest_t;
 
 /** Per method call config
@@ -90,6 +91,8 @@ struct call_env_parsed_s {
        size_t                  opt_count;      //!< Number of instances found of this option.
        size_t                  multi_index;    //!< Array index for this instance.
        call_env_t const        *rule;          //!< Used to produce this.
+       bool                    tmpl_only;      //!< Don't evaluate before module / xlat call.
+                                               ///< Only the tmpl reference is needed.
 };
 
 FR_DLIST_FUNCS(call_env_parsed, call_env_parsed_t, entry)
@@ -186,6 +189,17 @@ _Generic((((_s *)NULL)->_f), \
                  .type_name = FR_CALL_ENV_DST_TYPE_NAME(_struct, _field), \
                  .tmpl_offset = offsetof(_struct, _tmpl_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, _struct, _tmpl_field, _dflt, _dflt_quote, _required) \
+       .name = _name, \
+       .type = _cast_type, \
+       .dflt = _dflt, \
+       .dflt_quote = _dflt_quote, \
+       .pair = { .required = _required, \
+                 .type = CALL_ENV_TYPE_TMPL_ONLY, \
+                 .tmpl_offset = offsetof(_struct, _tmpl_field) }
+
 #define FR_CALL_ENV_SUBSECTION(_name, _ident2, _subcs ) \
        .name = _name, \
        .type = FR_TYPE_SUBSECTION, \