MEM(vpt = tmpl_alloc(trigger, TMPL_TYPE_EXEC, quote, value, talloc_array_length(value)));
tmpl_set_xlat(vpt, xlat);
- if (unlang_tmpl_push(trigger, &trigger->out, request, vpt,
+ if (unlang_tmpl_push(trigger, NULL, &trigger->out, request, vpt,
&(unlang_tmpl_args_t) {
.type = UNLANG_TMPL_ARGS_TYPE_EXEC,
.exec = {
ctx = *out;
}
- if (unlang_tmpl_push(ctx, &call_env_rctx->tmpl_expanded, request, call_env_rctx->last_expanded->data.tmpl,
+ if (unlang_tmpl_push(ctx, &call_env_rctx->expansion_result, &call_env_rctx->tmpl_expanded, request,
+ call_env_rctx->last_expanded->data.tmpl,
NULL) < 0) return UNLANG_ACTION_FAIL;
return UNLANG_ACTION_PUSHED_CHILD;
return 0;
case TMPL_TYPE_EXEC:
- if (unlang_tmpl_push(ctx, &out->result, request, vpt, NULL) < 0) return -1;
+ if (unlang_tmpl_push(ctx, &out->success, &out->result, request, vpt, NULL) < 0) return -1;
return 1;
case TMPL_TYPE_XLAT:
fr_value_box_list_init(&state->result);
- if (unlang_tmpl_push(state, &state->result, request, gext->vpt, NULL) < 0) return UNLANG_ACTION_FAIL;
+ if (unlang_tmpl_push(state, NULL, &state->result, request, gext->vpt, NULL) < 0) return UNLANG_ACTION_FAIL;
frame_repeat(frame, unlang_limit_xlat_done);
break;
case TMPL_TYPE_EXEC:
- if (unlang_tmpl_push(update_state, &update_state->lhs_result,
+ if (unlang_tmpl_push(update_state, NULL, &update_state->lhs_result,
request, map->lhs,
NULL) < 0) {
return UNLANG_ACTION_STOP_PROCESSING;
break;
case TMPL_TYPE_EXEC:
- if (unlang_tmpl_push(update_state, &update_state->rhs_result,
+ if (unlang_tmpl_push(update_state, NULL, &update_state->rhs_result,
request, map->rhs, NULL) < 0) {
return UNLANG_ACTION_STOP_PROCESSING;
}
break;
}
case TMPL_TYPE_EXEC:
- if (unlang_tmpl_push(map_proc_state, &map_proc_state->src_result,
+ if (unlang_tmpl_push(map_proc_state, NULL, &map_proc_state->src_result,
request, inst->src, NULL) < 0) {
return UNLANG_ACTION_STOP_PROCESSING;
}
/*
* Push the xlat function
*/
- if (unlang_tmpl_push(ctx, out, request, vpt, args) < 0) return UNLANG_ACTION_FAIL;
+ if (unlang_tmpl_push(ctx, NULL, out, request, vpt, args) < 0) return UNLANG_ACTION_FAIL;
return UNLANG_ACTION_PUSHED_CHILD;
}
fr_value_box_list_init(&state->result);
- if (unlang_tmpl_push(state, &state->result, request, gext->vpt, NULL) < 0) return UNLANG_ACTION_FAIL;
+ if (unlang_tmpl_push(state, NULL, &state->result, request, gext->vpt, NULL) < 0) return UNLANG_ACTION_FAIL;
frame_repeat(frame, unlang_timeout_done);
#include <freeradius-devel/unlang/tmpl.h>
#include <freeradius-devel/server/exec.h>
#include <freeradius-devel/util/syserror.h>
+#include <freeradius-devel/unlang/mod_action.h>
#include "tmpl_priv.h"
#include <signal.h>
*/
frame_repeat(frame, unlang_tmpl_exec_wait_resume);
push:
- if (unlang_xlat_push(state->ctx, &state->xlat_result, &state->list, request, tmpl_xlat(ut->tmpl), false) < 0) {
+ if (unlang_xlat_push(state->ctx, &state->xlat_result, &state->list, request, tmpl_xlat(ut->tmpl), UNLANG_SUB_FRAME) < 0) {
fail:
return UNLANG_ACTION_STOP_PROCESSING;
}
/** Push a tmpl onto the stack for evaluation
*
* @param[in] ctx To allocate value boxes and values in.
+ * @param[out] p_result The frame result
* @param[out] out The value_box created from the tmpl. May be NULL,
* in which case the result is discarded.
* @param[in] request The current request.
* - 0 on success
* - -1 on failure
*/
-int unlang_tmpl_push(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request,
+int unlang_tmpl_push(TALLOC_CTX *ctx, unlang_result_t *p_result, fr_value_box_list_t *out, request_t *request,
tmpl_t const *tmpl, unlang_tmpl_args_t *args)
{
unlang_stack_t *stack = request->stack;
unlang_tmpl_t *ut;
- static unlang_t tmpl_instruction = {
+ static unlang_t const tmpl_instruction_return = {
.type = UNLANG_TYPE_TMPL,
.name = "tmpl",
.debug_name = "tmpl",
},
};
+ static const unlang_t tmpl_instruction_fail = {
+ .type = UNLANG_TYPE_TMPL,
+ .name = "tmpl",
+ .debug_name = "tmpl",
+ .actions = DEFAULT_MOD_ACTIONS,
+ };
+
if (tmpl_needs_resolving(tmpl)) {
REDEBUG("Expansion \"%pV\" needs to be resolved before it is used", fr_box_strvalue_len(tmpl->name, tmpl->len));
return -1;
}
+ /*
+ * Avoid an extra stack frame and more work. But only if the caller hands us a result.
+ * Otherwise, we have to return UNLANG_FAIL.
+ */
+ if (p_result && (tmpl_rules_cast(tmpl) == FR_TYPE_NULL) && tmpl_is_xlat(tmpl)) {
+ return unlang_xlat_push(ctx, p_result, out, request, tmpl_xlat(tmpl), UNLANG_SUB_FRAME);
+ }
+
fr_assert(!tmpl_contains_regex(tmpl));
MEM(ut = talloc(stack, unlang_tmpl_t));
*ut = (unlang_tmpl_t){
- .self = tmpl_instruction,
+ .self = p_result ? tmpl_instruction_fail : tmpl_instruction_return,
.tmpl = tmpl
};
/*
* Push a new tmpl frame onto the stack
*/
- if (unlang_interpret_push(NULL, request, unlang_tmpl_to_generic(ut),
+ if (unlang_interpret_push(p_result, request, unlang_tmpl_to_generic(ut),
FRAME_CONF(RLM_MODULE_NOT_SET, false), UNLANG_NEXT_STOP) < 0) return -1;
frame = &stack->frame[stack->depth];
*/
typedef unlang_action_t (*fr_unlang_tmpl_resume_t)(unlang_result_t *p_result, request_t *request, void *rctx);
-int unlang_tmpl_push(TALLOC_CTX *ctx, fr_value_box_list_t *out,
+int unlang_tmpl_push(TALLOC_CTX *ctx, unlang_result_t *p_result, fr_value_box_list_t *out,
request_t *request, tmpl_t const *tmpl, unlang_tmpl_args_t *args)
CC_HINT(warn_unused_result);
/** Push a pre-compiled xlat onto the stack for evaluation
*
* @param[in] ctx To allocate value boxes and values in.
+ * @param[out] p_result The frame result
* @param[out] out Where to write the result of the expansion.
* @param[in] request to push xlat onto.
* @param[in] xlat to evaluate.
if (unlang_xlat_yield(request, xlat_exec_resume, NULL, 0, rctx) != XLAT_ACTION_YIELD) goto fail;
- if (unlang_tmpl_push(ctx, &rctx->list, request, node->vpt,
+ if (unlang_tmpl_push(ctx, NULL, &rctx->list, request, node->vpt,
TMPL_ARGS_EXEC(NULL, fr_time_delta_from_sec(EXEC_TIMEOUT),
false, &rctx->status)) < 0) goto fail;
RETURN_UNLANG_FAIL;
}
- if (unlang_tmpl_push(group_ctx, &group_ctx->expanded_filter, request, autz_ctx->call_env->group_filter, NULL) < 0) goto error;
+ if (unlang_tmpl_push(group_ctx, NULL, &group_ctx->expanded_filter, request, autz_ctx->call_env->group_filter, NULL) < 0) goto error;
return UNLANG_ACTION_PUSHED_CHILD;
}
RETURN_UNLANG_FAIL;
}
- if (unlang_tmpl_push(group_ctx, &group_ctx->expanded_filter, request, group_ctx->filter_tmpl, NULL) < 0) goto error;
+ if (unlang_tmpl_push(group_ctx, NULL, &group_ctx->expanded_filter, request, group_ctx->filter_tmpl, NULL) < 0) goto error;
return UNLANG_ACTION_PUSHED_CHILD;
}
*/
if (usermod_ctx->current_mod < usermod_ctx->num_mods) {
if (unlang_module_yield(request, user_modify_mod_build_resume, NULL, 0, usermod_ctx) == UNLANG_ACTION_FAIL) RETURN_UNLANG_FAIL;
- if (unlang_tmpl_push(usermod_ctx, &usermod_ctx->expanded, request,
+ if (unlang_tmpl_push(usermod_ctx, NULL, &usermod_ctx->expanded, request,
usermod_ctx->call_env->mod[usermod_ctx->current_mod]->tmpl, NULL) < 0) RETURN_UNLANG_FAIL;
return UNLANG_ACTION_PUSHED_CHILD;
}
if (unlang_module_yield(request, user_modify_mod_build_resume, NULL, 0, usermod_ctx) == UNLANG_ACTION_FAIL) goto fail;
;
- if (unlang_tmpl_push(usermod_ctx, &usermod_ctx->expanded, request,
+ if (unlang_tmpl_push(usermod_ctx, NULL, &usermod_ctx->expanded, request,
usermod_ctx->call_env->mod[0]->tmpl, NULL) < 0) goto fail;
return UNLANG_ACTION_PUSHED_CHILD;
}
fr_value_box_list_init(&auth_ctx->cpw_ctx->local_cpw_result);
- if (unlang_tmpl_push(auth_ctx, &auth_ctx->cpw_ctx->local_cpw_result, request,
+ if (unlang_tmpl_push(auth_ctx, NULL, &auth_ctx->cpw_ctx->local_cpw_result, request,
env_data->local_cpw, NULL) < 0) RETURN_UNLANG_FAIL;
break;
#else
*/
if (env_data->ntlm_cpw_domain) {
fr_value_box_list_init(&auth_ctx->cpw_ctx->cpw_domain);
- if (unlang_tmpl_push(auth_ctx, &auth_ctx->cpw_ctx->cpw_domain, request,
+ if (unlang_tmpl_push(auth_ctx, NULL, &auth_ctx->cpw_ctx->cpw_domain, request,
env_data->ntlm_cpw_domain, NULL) < 0) RETURN_UNLANG_FAIL;
}
/*
* b) Expanding the username
*/
- if (unlang_tmpl_push(auth_ctx, &auth_ctx->cpw_ctx->cpw_user, request,
+ if (unlang_tmpl_push(auth_ctx, NULL, &auth_ctx->cpw_ctx->cpw_user, request,
env_data->ntlm_cpw_username, NULL) < 0) RETURN_UNLANG_FAIL;
break;
}
fr_value_box_list_init(&xlat_ctx->query);
if (unlang_xlat_yield(request, sql_group_xlat_resume, NULL, 0, xlat_ctx) != XLAT_ACTION_YIELD) return XLAT_ACTION_FAIL;
- if (unlang_tmpl_push(xlat_ctx, &xlat_ctx->query, request, call_env->membership_query, NULL) < 0) return XLAT_ACTION_FAIL;
+ if (unlang_tmpl_push(xlat_ctx, NULL, &xlat_ctx->query, request, call_env->membership_query, NULL) < 0) return XLAT_ACTION_FAIL;
return XLAT_ACTION_PUSH_UNLANG;
}
if (call_env->group_check_query) {
if (unlang_module_yield(request, mod_autz_group_resume, NULL, 0, mctx->rctx) == UNLANG_ACTION_FAIL) RETURN_UNLANG_FAIL;
- if (unlang_tmpl_push(autz_ctx, &autz_ctx->query, request,
+ if (unlang_tmpl_push(autz_ctx, NULL, &autz_ctx->query, request,
call_env->group_check_query, NULL) < 0) RETURN_UNLANG_FAIL;
return UNLANG_ACTION_PUSHED_CHILD;
}
if (call_env->group_reply_query) {
group_reply_push:
if (unlang_module_yield(request, mod_autz_group_resume, NULL, 0, mctx->rctx) == UNLANG_ACTION_FAIL) RETURN_UNLANG_FAIL;
- if (unlang_tmpl_push(autz_ctx, &autz_ctx->query, request,
+ if (unlang_tmpl_push(autz_ctx, NULL, &autz_ctx->query, request,
call_env->group_reply_query, NULL) < 0) RETURN_UNLANG_FAIL;
autz_ctx->status = autz_ctx->status & SQL_AUTZ_STAGE_GROUP ? SQL_AUTZ_GROUP_REPLY : SQL_AUTZ_PROFILE_REPLY;
return UNLANG_ACTION_PUSHED_CHILD;
if (!call_env->reply_query) goto skip_reply;
if (unlang_module_yield(request, mod_authorize_resume, NULL, 0, autz_ctx) == UNLANG_ACTION_FAIL) RETURN_UNLANG_FAIL;
- if (unlang_tmpl_push(autz_ctx, &autz_ctx->query, request, call_env->reply_query, NULL) < 0) RETURN_UNLANG_FAIL;
+ if (unlang_tmpl_push(autz_ctx, NULL, &autz_ctx->query, request, call_env->reply_query, NULL) < 0) RETURN_UNLANG_FAIL;
autz_ctx->status = SQL_AUTZ_REPLY;
return UNLANG_ACTION_PUSHED_CHILD;
}
if (unlang_module_yield(request, mod_autz_group_resume, NULL, 0, autz_ctx) == UNLANG_ACTION_FAIL) RETURN_UNLANG_FAIL;
- if (unlang_tmpl_push(autz_ctx, &autz_ctx->query, request,
+ if (unlang_tmpl_push(autz_ctx, NULL, &autz_ctx->query, request,
call_env->membership_query, NULL) < 0) RETURN_UNLANG_FAIL;
autz_ctx->status = SQL_AUTZ_GROUP_MEMB;
return UNLANG_ACTION_PUSHED_CHILD;
* Query the check table to find any conditions associated with this user/realm/whatever...
*/
if (call_env->check_query) {
- if (unlang_tmpl_push(autz_ctx, &autz_ctx->query, request, call_env->check_query, NULL) < 0) goto error;
+ if (unlang_tmpl_push(autz_ctx, NULL, &autz_ctx->query, request, call_env->check_query, NULL) < 0) goto error;
autz_ctx->status = SQL_AUTZ_CHECK;
return UNLANG_ACTION_PUSHED_CHILD;
}
if (call_env->reply_query) {
- if (unlang_tmpl_push(autz_ctx, &autz_ctx->query, request, call_env->reply_query, NULL) < 0) goto error;
+ if (unlang_tmpl_push(autz_ctx, NULL, &autz_ctx->query, request, call_env->reply_query, NULL) < 0) goto error;
autz_ctx->status = SQL_AUTZ_REPLY;
return UNLANG_ACTION_PUSHED_CHILD;
}
/*
* Neither check nor reply queries were set, so we must be doing group stuff
*/
- if (unlang_tmpl_push(autz_ctx, &autz_ctx->query, request, call_env->membership_query, NULL) < 0) goto error;
+ if (unlang_tmpl_push(autz_ctx, NULL, &autz_ctx->query, request, call_env->membership_query, NULL) < 0) goto error;
autz_ctx->status = SQL_AUTZ_GROUP_MEMB;
return UNLANG_ACTION_PUSHED_CHILD;
}
redundant_ctx->query_no++;
if (redundant_ctx->query_no >= talloc_array_length(call_env->query)) RETURN_UNLANG_NOOP;
if (unlang_module_yield(request, mod_sql_redundant_resume, NULL, 0, redundant_ctx) == UNLANG_ACTION_FAIL) RETURN_UNLANG_FAIL;
- if (unlang_tmpl_push(redundant_ctx, &redundant_ctx->query, request, call_env->query[redundant_ctx->query_no], NULL) < 0) RETURN_UNLANG_FAIL;
+ if (unlang_tmpl_push(redundant_ctx, NULL, &redundant_ctx->query, request, call_env->query[redundant_ctx->query_no], NULL) < 0) RETURN_UNLANG_FAIL;
RDEBUG2("Trying next query...");
if (env->existing) {
alloc_ctx->status = IPPOOL_ALLOC_EXISTING;
REPEAT_MOD_ALLOC_RESUME;
- if (unlang_tmpl_push(alloc_ctx, &alloc_ctx->values, request, env->existing, NULL) < 0) {
+ if (unlang_tmpl_push(alloc_ctx, NULL, &alloc_ctx->values, request, env->existing, NULL) < 0) {
error:
talloc_free(alloc_ctx);
RETURN_UNLANG_FAIL;
if (env->requested && (env->requested_address.type != FR_TYPE_NULL)) {
alloc_ctx->status = IPPOOL_ALLOC_REQUESTED;
REPEAT_MOD_ALLOC_RESUME;
- if (unlang_tmpl_push(alloc_ctx, &alloc_ctx->values, request, env->requested, NULL) < 0) goto error;
+ if (unlang_tmpl_push(alloc_ctx, NULL, &alloc_ctx->values, request, env->requested, NULL) < 0) goto error;
return UNLANG_ACTION_PUSHED_CHILD;
}
goto expand_find;
*/
alloc_ctx->status = IPPOOL_ALLOC_FIND;
REPEAT_MOD_ALLOC_RESUME;
- if (unlang_tmpl_push(alloc_ctx, &alloc_ctx->values, request, env->find, NULL) < 0) goto error;
+ if (unlang_tmpl_push(alloc_ctx, NULL, &alloc_ctx->values, request, env->find, NULL) < 0) goto error;
return UNLANG_ACTION_PUSHED_CHILD;
case IPPOOL_ALLOC_FIND:
if (env->pool_check) {
alloc_ctx->status = IPPOOL_ALLOC_POOL_CHECK;
REPEAT_MOD_ALLOC_RESUME;
- if (unlang_tmpl_push(alloc_ctx, &alloc_ctx->values, request, env->pool_check, NULL) < 0) goto error;
+ if (unlang_tmpl_push(alloc_ctx, NULL, &alloc_ctx->values, request, env->pool_check, NULL) < 0) goto error;
return UNLANG_ACTION_PUSHED_CHILD;
}
no_address:
if (env->update) {
alloc_ctx->status = IPPOOL_ALLOC_UPDATE;
REPEAT_MOD_ALLOC_RESUME;
- if (unlang_tmpl_push(alloc_ctx, &alloc_ctx->values, request, env->update, NULL) < 0) goto error;
+ if (unlang_tmpl_push(alloc_ctx, NULL, &alloc_ctx->values, request, env->update, NULL) < 0) goto error;
return UNLANG_ACTION_PUSHED_CHILD;
}