]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Fix multiple issues with unlang function calls and make the code a bit more understan...
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 3 Jun 2021 23:23:11 +0000 (18:23 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 3 Jun 2021 23:23:11 +0000 (18:23 -0500)
src/lib/unlang/function.c

index 12daba5cd3907391ac74e5863596af1eb46f666d..64adfa62b64c62373553293a0a31930e621c71ae 100644 (file)
@@ -32,7 +32,6 @@ RCSID("$Id$")
  *     Some functions differ mainly in their parsing
  */
 typedef struct {
-       bool                            done_func;              //!< Set to true after func has been executed.
        unlang_function_t               func;                   //!< To call when going down the stack.
        unlang_function_t               repeat;                 //!< To call when going back up the stack.
        unlang_function_signal_t        signal;                 //!< Signal function to call.
@@ -75,6 +74,27 @@ static void unlang_function_signal(request_t *request,
        state->signal(request, action, state->uctx);
 }
 
+static unlang_action_t unlang_function_call_repeat(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
+{
+       unlang_action_t                 ua;
+       unlang_frame_state_func_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_func_t);
+       char const                      *caller;
+
+       *p_result = RLM_MODULE_NOOP;    /* Avoid asserts */
+
+       /*
+        *      Don't let the callback mess with the current
+        *      module permanently.
+        */
+       caller = request->module;
+       request->module = NULL;
+       RDEBUG4("Calling repeat function %p", state->repeat);
+       ua = state->repeat(p_result, &frame->priority, request, state->uctx);
+       request->module = caller;
+
+       return ua;
+}
+
 /** Call a generic function
  *
  * @param[out] p_result                The frame result.
@@ -83,21 +103,26 @@ static void unlang_function_signal(request_t *request,
  */
 static unlang_action_t unlang_function_call(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_frame_state_func_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_func_t);
        unlang_action_t                 ua;
+       unlang_frame_state_func_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_func_t);
        char const                      *caller;
 
+       *p_result = RLM_MODULE_NOOP;    /* Avoid asserts */
+
        /*
         *      Don't let the callback mess with the current
         *      module permanently.
         */
        caller = request->module;
        request->module = NULL;
-       if (!state->done_func && state->func) {
-               ua = state->func(p_result, &frame->priority, request, state->uctx);
-               state->done_func = true;
-       } else {
-               ua = state->repeat(p_result, &frame->priority, request, state->uctx);
+
+       RDEBUG4("Calling function %p", state->func);
+       ua = state->func(p_result, &frame->priority, request, state->uctx);
+       if (ua != UNLANG_ACTION_STOP_PROCESSING) {
+               if (state->repeat) {
+                       frame->process = unlang_function_call_repeat;
+                       repeatable_set(frame);
+               }
        }
        request->module = caller;
 
@@ -149,6 +174,11 @@ int unlang_interpret_push_function(request_t *request, unlang_function_t func, u
        state->signal = signal;
        state->uctx = uctx;
 
+       /*
+        *      Just skip to the repeat state directly
+        */
+       if (!func && repeat) frame->process = unlang_function_call_repeat;
+
        return 0;
 }