From: Nick Porter Date: Wed, 7 Jun 2023 13:44:24 +0000 (+0100) Subject: Add tmpl only call environment entries X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b0cfbf8eca307608905b8918a4f9b6476b32ff73;p=thirdparty%2Ffreeradius-server.git Add tmpl only call environment entries For use where the requirement is just a tmpl to produce output pair(s) --- diff --git a/src/lib/unlang/call_env.c b/src/lib/unlang/call_env.c index 1be1f439add..610c3a18dd8 100644 --- a/src/lib/unlang/call_env.c +++ b/src/lib/unlang/call_env.c @@ -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, diff --git a/src/lib/unlang/call_env.h b/src/lib/unlang/call_env.h index 1ca2acdac2c..3051d74399f 100644 --- a/src/lib/unlang/call_env.h +++ b/src/lib/unlang/call_env.h @@ -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, \