From: Alan T. DeKok Date: Thu, 19 May 2022 14:39:49 +0000 (-0400) Subject: update APIs to allow for "evaluate only one node" X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f05299e836e56be93f56fafd0572f43148694b2f;p=thirdparty%2Ffreeradius-server.git update APIs to allow for "evaluate only one node" instead of looping through everything --- diff --git a/src/lib/unlang/xlat.c b/src/lib/unlang/xlat.c index 7edace23758..89a65efe8ee 100644 --- a/src/lib/unlang/xlat.c +++ b/src/lib/unlang/xlat.c @@ -178,15 +178,16 @@ int unlang_xlat_timeout_add(request_t *request, * here. If execution fails, false will be written. * @param[out] out Where to write the result of the expansion. * @param[in] request to push xlat onto. - * @param[in] xlat to evaluate. + * @param[in] xlat head of list + * @param[in] node to evaluate. * @param[in] top_frame Set to UNLANG_TOP_FRAME if the interpreter should return. * Set to UNLANG_SUB_FRAME if the interprer should continue. * @return * - 0 on success. * - -1 on failure. */ -int unlang_xlat_push(TALLOC_CTX *ctx, bool *p_success, fr_value_box_list_t *out, - request_t *request, xlat_exp_head_t const *xlat, bool top_frame) +static int unlang_xlat_push_internal(TALLOC_CTX *ctx, bool *p_success, fr_value_box_list_t *out, + request_t *request, xlat_exp_head_t const *xlat, xlat_exp_t *node, bool top_frame) { /** Static instruction for performing xlat evaluations * @@ -226,8 +227,8 @@ int unlang_xlat_push(TALLOC_CTX *ctx, bool *p_success, fr_value_box_list_t *out, * Allocate its state, and setup a cursor for the xlat nodes */ MEM(frame->state = state = talloc_zero(stack, unlang_frame_state_xlat_t)); - state->head = talloc_get_type_abort_const(xlat, xlat_exp_head_t); /* Ensure the node is valid */ - state->exp = xlat_exp_head(state->head); + state->head = xlat; + state->exp = node; state->success = p_success; state->ctx = ctx; @@ -240,6 +241,46 @@ int unlang_xlat_push(TALLOC_CTX *ctx, bool *p_success, fr_value_box_list_t *out, return 0; } +/** Push a pre-compiled xlat onto the stack for evaluation + * + * @param[in] ctx To allocate value boxes and values in. + * @param[out] p_success If set, and execution succeeds, true will be written + * here. If execution fails, false will be written. + * @param[out] out Where to write the result of the expansion. + * @param[in] request to push xlat onto. + * @param[in] xlat to evaluate. + * @param[in] top_frame Set to UNLANG_TOP_FRAME if the interpreter should return. + * Set to UNLANG_SUB_FRAME if the interprer should continue. + * @return + * - 0 on success. + * - -1 on failure. + */ +int unlang_xlat_push(TALLOC_CTX *ctx, bool *p_success, fr_value_box_list_t *out, + request_t *request, xlat_exp_head_t const *xlat, bool top_frame) +{ + (void) talloc_get_type_abort_const(xlat, xlat_exp_head_t); + + return unlang_xlat_push_internal(ctx, p_success, out, request, xlat, xlat_exp_head(xlat), top_frame); +} + +/** Push a pre-compiled xlat onto the stack for evaluation + * + * @param[in] ctx To allocate value boxes and values in. + * @param[out] p_success If set, and execution succeeds, true will be written + * here. If execution fails, false will be written. + * @param[out] out Where to write the result of the expansion. + * @param[in] request to push xlat onto. + * @param[in] node to evaluate. Only this node will be evaluated. + * @return + * - 0 on success. + * - -1 on failure. + */ +int unlang_xlat_push_node(TALLOC_CTX *ctx, bool *p_success, fr_value_box_list_t *out, + request_t *request, xlat_exp_t *node) +{ + return unlang_xlat_push_internal(ctx, p_success, out, request, NULL, node, UNLANG_TOP_FRAME); +} + static unlang_action_t unlang_xlat_repeat(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame) { unlang_frame_state_xlat_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_xlat_t); diff --git a/src/lib/unlang/xlat_priv.h b/src/lib/unlang/xlat_priv.h index 82e86a51091..67581289bc1 100644 --- a/src/lib/unlang/xlat_priv.h +++ b/src/lib/unlang/xlat_priv.h @@ -311,6 +311,9 @@ void xlat_eval_free(void); void unlang_xlat_init(void); +int unlang_xlat_push_node(TALLOC_CTX *ctx, bool *p_success, fr_value_box_list_t *out, + request_t *request, xlat_exp_t *node); + int xlat_decode_value_box_list(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, void *decode_ctx, fr_pair_decode_t decode, fr_value_box_list_t *in); @@ -349,6 +352,8 @@ static inline xlat_exp_t *xlat_exp_head(xlat_exp_head_t const *head) static inline xlat_exp_t *xlat_exp_next(xlat_exp_head_t const *head, xlat_exp_t const *node) { + if (!head) return NULL; + return fr_dlist_next(&head->dlist, node); }