]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
make global "timeout" section work
authorAlan T. DeKok <aland@freeradius.org>
Fri, 18 Apr 2025 18:51:22 +0000 (14:51 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 18 Apr 2025 18:51:22 +0000 (14:51 -0400)
with some tweaks to unlang_timeout_section_push() to make it work
and indent the request correctly.

src/lib/server/virtual_servers.c
src/lib/unlang/timeout.c
src/lib/unlang/timeout.h

index cf0f9e7295d455896c9b1921bd688947ca5954d3..9ec32430e24d248512635d02d86079f86183ae16 100644 (file)
@@ -70,6 +70,7 @@ struct virtual_server_s {
 
        fr_time_delta_t                 timeout_delay;          //!< for timeout sections
        void                            *timeout_instruction;   //!< the timeout instruction
+       CONF_SECTION                    *timeout_cs;
 };
 
 static fr_dict_t const *dict_freeradius;
@@ -715,6 +716,17 @@ unlang_action_t virtual_server_push(request_t *request, CONF_SECTION *server_cs,
                }
        }
 
+       /*
+        *      Push a timeout after updating the log destination.
+        */
+       if (server->timeout_cs) {
+               if (unlang_timeout_section_push(request, server->timeout_cs, server->timeout_delay, top_frame) < 0) {
+                       return UNLANG_ACTION_FAIL;
+               }
+
+               top_frame = UNLANG_SUB_FRAME;
+       }
+
        /*
         *      Bootstrap the stack with a module instance.
         */
@@ -1133,6 +1145,7 @@ static int virtual_server_compile_sections(virtual_server_t *vs, tmpl_rules_t co
 
                vs->timeout_delay = box.vb_time_delta;
                vs->timeout_instruction = instruction;
+               vs->timeout_cs = subcs;
 
                found++;
        }
index 8349f7aee641f699182893679ca9fca000fa1b8a..233115d99b2a667e4c9b6fa10861cebf2570d6e6 100644 (file)
@@ -60,6 +60,8 @@ static void unlang_timeout_handler(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t
        unlang_frame_signal(request, FR_SIGNAL_CANCEL, state->depth);
        state->success = false;
 
+       RINDENT_RESTORE(request, state);
+
        if (!state->instruction) return;
 
        if (unlang_interpret_push_instruction(request, state->instruction, RLM_MODULE_FAIL, true) < 0) {
@@ -72,8 +74,6 @@ static unlang_action_t unlang_timeout_resume_done(UNUSED rlm_rcode_t *p_result,
        unlang_frame_state_timeout_t    *state = talloc_get_type_abort(frame->state, unlang_frame_state_timeout_t);
 
        if (!state->success) {
-               RINDENT_RESTORE(request, state);
-
                RWDEBUG("Timeout exceeded");
                return UNLANG_ACTION_FAIL;
        }
@@ -149,14 +149,16 @@ static unlang_action_t unlang_timeout(rlm_rcode_t *p_result, request_t *request,
 /** When a timeout fires, run the given section.
  *
  * @param[in] request          to push timeout onto
- * @param[in] timeout          when to run the timeout
+ * @param[in] timeout          when to run the timeout
  * @param[in] cs               section to run when the timeout fires.
+ * @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_timeout_section_push(request_t *request, CONF_SECTION *cs, fr_time_delta_t timeout)
+int unlang_timeout_section_push(request_t *request, CONF_SECTION *cs, fr_time_delta_t timeout, bool top_frame)
 {
        /** Static instruction for performing xlat evaluations
         *
@@ -185,6 +187,7 @@ int unlang_timeout_section_push(request_t *request, CONF_SECTION *cs, fr_time_de
        unlang_stack_t                  *stack = request->stack;
        unlang_stack_frame_t            *frame;
        unlang_t                        *instruction;
+       fr_time_t                       when;
 
        /*
         *      Get the instruction we are supposed to run on timeout.
@@ -200,7 +203,7 @@ int unlang_timeout_section_push(request_t *request, CONF_SECTION *cs, fr_time_de
         *      Push a new timeout frame onto the stack
         */
        if (unlang_interpret_push(request, &timeout_instruction,
-                                 RLM_MODULE_NOT_SET, UNLANG_NEXT_STOP, true) < 0) return -1;
+                                 RLM_MODULE_NOT_SET, UNLANG_NEXT_STOP, top_frame) < 0) return -1;
        frame = &stack->frame[stack->depth];
 
        /*
@@ -208,15 +211,23 @@ int unlang_timeout_section_push(request_t *request, CONF_SECTION *cs, fr_time_de
         */
        MEM(frame->state = state = talloc_zero(stack, unlang_frame_state_timeout_t));
 
+       RINDENT_SAVE(state, request);
+       state->depth = stack->depth;
+       state->request = request;
        state->timeout = timeout;
        state->instruction = instruction;
+       state->success = true;
 
-       if (unlang_timeout_set(&request->rcode, request, frame) != UNLANG_ACTION_PUSHED_CHILD) {
-               REDEBUG("Failed set timer for section %s { ... }",
-                       cf_section_name1(cs));
+       when = fr_time_add(fr_time(), timeout);
+
+       if (fr_timer_at(state, unlang_interpret_event_list(request)->tl, &state->ev, when,
+                       false, unlang_timeout_handler, state) < 0) {
+               RPEDEBUG("Failed setting timeout for section %s", cf_section_name1(cs));
                return -1;
        }
 
+       frame_repeat(frame, unlang_timeout_resume_done);
+
        return 0;
 
 }
index 6daf3729254860d01bf3ff337563e56a942212b8..16947adba169c878af60b45974853c84ffd4838e 100644 (file)
@@ -29,7 +29,7 @@
 extern "C" {
 #endif
 
-int    unlang_timeout_section_push(request_t *request, CONF_SECTION *cs, fr_time_delta_t timeout) CC_HINT(nonnull);
+int    unlang_timeout_section_push(request_t *request, CONF_SECTION *cs, fr_time_delta_t timeout, bool top_frame) CC_HINT(nonnull);
 
 #ifdef __cplusplus
 }