From: Alan T. DeKok Date: Fri, 18 Apr 2025 18:51:22 +0000 (-0400) Subject: make global "timeout" section work X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=50cc1570a12257548d24cba856a0e5f6483a4fec;p=thirdparty%2Ffreeradius-server.git make global "timeout" section work with some tweaks to unlang_timeout_section_push() to make it work and indent the request correctly. --- diff --git a/src/lib/server/virtual_servers.c b/src/lib/server/virtual_servers.c index cf0f9e7295d..9ec32430e24 100644 --- a/src/lib/server/virtual_servers.c +++ b/src/lib/server/virtual_servers.c @@ -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++; } diff --git a/src/lib/unlang/timeout.c b/src/lib/unlang/timeout.c index 8349f7aee64..233115d99b2 100644 --- a/src/lib/unlang/timeout.c +++ b/src/lib/unlang/timeout.c @@ -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; } diff --git a/src/lib/unlang/timeout.h b/src/lib/unlang/timeout.h index 6daf3729254..16947adba16 100644 --- a/src/lib/unlang/timeout.h +++ b/src/lib/unlang/timeout.h @@ -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 }