mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
Merge d40aae52da
into 3dd4d417be
This commit is contained in:
commit
471f51374e
|
@ -83,6 +83,18 @@ and the :clicmd:`terminal paginate` command:
|
|||
(likely ``more`` or ``/usr/bin/pager``) will be used.
|
||||
|
||||
|
||||
Idle Timeout
|
||||
============
|
||||
|
||||
.. clicmd:: exec-timeout TIMEOUT
|
||||
|
||||
Enable an idle timeout for the vtysh session, in seconds. When
|
||||
configured, the vtysh process will exit if the session is
|
||||
idle. The timeout can be configured via ``vtysh.conf``, via a
|
||||
``-T, --exec-timeout`` command-line option, or in the configure
|
||||
mode. A timeout of zero is equivalent to "no timeout".
|
||||
|
||||
|
||||
Permissions and setup requirements
|
||||
==================================
|
||||
|
||||
|
|
|
@ -4253,6 +4253,21 @@ DEFUN (vtysh_show_daemons,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (vtysh_exec_timeout,
|
||||
vtysh_exec_timeout_cmd,
|
||||
"[no$nono] exec-timeout ![(0-1000000)$tsecs]",
|
||||
NO_STR
|
||||
"Set the VTYSH EXEC timeout\n"
|
||||
"Timeout in seconds\n")
|
||||
{
|
||||
if (nono)
|
||||
tsecs = 0;
|
||||
|
||||
vtysh_exec_timeout_config(tsecs);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
struct visual_prio {
|
||||
/* 4 characters for nice alignment */
|
||||
const char *label;
|
||||
|
@ -5669,4 +5684,5 @@ void vtysh_init_vty(void)
|
|||
install_element(CONFIG_NODE, &no_vtysh_password_cmd);
|
||||
install_element(CONFIG_NODE, &vtysh_enable_password_cmd);
|
||||
install_element(CONFIG_NODE, &no_vtysh_enable_password_cmd);
|
||||
install_element(CONFIG_NODE, &vtysh_exec_timeout_cmd);
|
||||
}
|
||||
|
|
|
@ -149,6 +149,11 @@ void vtysh_config_init(void);
|
|||
void suid_on(void);
|
||||
void suid_off(void);
|
||||
|
||||
/* Handle exec-timeout config changes */
|
||||
#define VTYSH_EXEC_TIMEOUT_MAX 1000 * 1000
|
||||
void vtysh_exec_timeout_config(uint32_t tsecs);
|
||||
uint32_t vtysh_get_exec_timeout(void);
|
||||
|
||||
/* Child process execution flag. */
|
||||
extern int execute_flag;
|
||||
|
||||
|
|
|
@ -767,6 +767,7 @@ void vtysh_config_write(void)
|
|||
{
|
||||
const char *name;
|
||||
char line[512];
|
||||
uint32_t ival;
|
||||
|
||||
name = cmd_hostname_get();
|
||||
if (name && name[0] != '\0') {
|
||||
|
@ -787,6 +788,12 @@ void vtysh_config_write(void)
|
|||
vtysh_config_parse_line(NULL,
|
||||
"service integrated-vtysh-config");
|
||||
|
||||
ival = vtysh_get_exec_timeout();
|
||||
if (ival > 0) {
|
||||
snprintf(line, sizeof(line), "exec-timeout %u", ival);
|
||||
vtysh_config_parse_line(NULL, line);
|
||||
}
|
||||
|
||||
user_config_write();
|
||||
}
|
||||
|
||||
|
|
|
@ -71,11 +71,72 @@ struct event_loop *master;
|
|||
/* Command logging */
|
||||
FILE *logfile;
|
||||
|
||||
static struct event *ev_exec_timeout;
|
||||
uint32_t vtysh_exec_timeout;
|
||||
|
||||
static void handle_exec_timeout(struct event *event);
|
||||
|
||||
/*
|
||||
* Disable/disarm the exec timeout
|
||||
*/
|
||||
static void disable_exec_timeout(void)
|
||||
{
|
||||
event_cancel(&ev_exec_timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable/arm the exec timeout, if configured
|
||||
*/
|
||||
static void enable_exec_timeout(void)
|
||||
{
|
||||
/* This may be called quite early; ensure the event-loop is running */
|
||||
if (master != NULL && vtysh_exec_timeout > 0)
|
||||
event_add_timer(master, handle_exec_timeout, NULL,
|
||||
vtysh_exec_timeout, &ev_exec_timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for exec-timeout config changes; takes timeout in seconds, and zero
|
||||
* means "no timeout"
|
||||
*/
|
||||
void vtysh_exec_timeout_config(uint32_t tsecs)
|
||||
{
|
||||
vtysh_exec_timeout = tsecs;
|
||||
disable_exec_timeout();
|
||||
|
||||
if (vtysh_exec_timeout > 0)
|
||||
enable_exec_timeout();
|
||||
}
|
||||
|
||||
/*
|
||||
* Accessor for configured exec timeout
|
||||
*/
|
||||
uint32_t vtysh_get_exec_timeout(void)
|
||||
{
|
||||
return vtysh_exec_timeout;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for exec timeout timer
|
||||
*/
|
||||
static void handle_exec_timeout(struct event *event)
|
||||
{
|
||||
rl_callback_handler_remove();
|
||||
|
||||
/* Execute "end" command. */
|
||||
vtysh_execute("end");
|
||||
|
||||
vtysh_loop_exited = true;
|
||||
|
||||
printf("Vtysh timed-out, exiting\n");
|
||||
}
|
||||
|
||||
static void vtysh_rl_callback(char *line_read)
|
||||
{
|
||||
HIST_ENTRY *last;
|
||||
|
||||
rl_callback_handler_remove();
|
||||
disable_exec_timeout();
|
||||
|
||||
if (!line_read) {
|
||||
vtysh_loop_exited = true;
|
||||
|
@ -96,8 +157,10 @@ static void vtysh_rl_callback(char *line_read)
|
|||
|
||||
vtysh_execute(line_read);
|
||||
|
||||
if (!vtysh_loop_exited)
|
||||
if (!vtysh_loop_exited) {
|
||||
rl_callback_handler_install(vtysh_prompt(), vtysh_rl_callback);
|
||||
enable_exec_timeout();
|
||||
}
|
||||
|
||||
free(line_read);
|
||||
}
|
||||
|
@ -182,6 +245,7 @@ static FRR_NORETURN void usage(int status)
|
|||
"-H, --histfile Override history file\n"
|
||||
"-t, --timestamp Print a timestamp before going to shell or reading the configuration\n"
|
||||
" --no-fork Don't fork clients to handle daemons (slower for large configs)\n"
|
||||
"-T, --exec-timeout Set an idle timeout for this vtysh session\n"
|
||||
"-h, --help Display this help and exit\n\n"
|
||||
"Note that multiple commands may be executed from the command\n"
|
||||
"line by passing multiple -c args, or by embedding linefeed\n"
|
||||
|
@ -216,6 +280,7 @@ struct option longopts[] = {
|
|||
{"user", no_argument, NULL, 'u'},
|
||||
{"timestamp", no_argument, NULL, 't'},
|
||||
{"no-fork", no_argument, NULL, OPTION_NOFORK},
|
||||
{"exec-timeout", required_argument, NULL, 'T'},
|
||||
{0}};
|
||||
|
||||
bool vtysh_loop_exited;
|
||||
|
@ -226,9 +291,13 @@ static void vtysh_rl_read(struct event *thread)
|
|||
{
|
||||
bool *suppress_warnings = EVENT_ARG(thread);
|
||||
|
||||
disable_exec_timeout();
|
||||
|
||||
event_add_read(master, vtysh_rl_read, suppress_warnings, STDIN_FILENO,
|
||||
&vtysh_rl_read_thread);
|
||||
rl_callback_read_char();
|
||||
|
||||
enable_exec_timeout();
|
||||
}
|
||||
|
||||
/* Read a string, and return a pointer to it. Returns NULL on EOF. */
|
||||
|
@ -243,6 +312,8 @@ static void vtysh_rl_run(void)
|
|||
event_add_read(master, vtysh_rl_read, &suppress_warnings, STDIN_FILENO,
|
||||
&vtysh_rl_read_thread);
|
||||
|
||||
enable_exec_timeout();
|
||||
|
||||
while (!vtysh_loop_exited && event_fetch(master, &thread))
|
||||
event_call(&thread);
|
||||
|
||||
|
@ -351,6 +422,7 @@ int main(int argc, char **argv, char **env)
|
|||
const char *histfile = NULL;
|
||||
const char *histfile_env = getenv("VTYSH_HISTFILE");
|
||||
const char *logpath = getenv("VTYSH_LOG");
|
||||
int exec_timeout = 0;
|
||||
|
||||
/* SUID: drop down to calling user & go back up when needed */
|
||||
elevuid = geteuid();
|
||||
|
@ -370,8 +442,7 @@ int main(int argc, char **argv, char **env)
|
|||
|
||||
/* Option handling. */
|
||||
while (1) {
|
||||
opt = getopt_long(argc, argv, "be:c:d:nf:H:mEhCwN:ut", longopts,
|
||||
0);
|
||||
opt = getopt_long(argc, argv, "be:c:d:nf:H:mEhCwN:utT:", longopts, 0);
|
||||
|
||||
if (opt == EOF)
|
||||
break;
|
||||
|
@ -447,6 +518,13 @@ int main(int argc, char **argv, char **env)
|
|||
case 'H':
|
||||
histfile = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
exec_timeout = atoi(optarg);
|
||||
if (exec_timeout < 0 || exec_timeout > VTYSH_EXEC_TIMEOUT_MAX) {
|
||||
fprintf(stderr, "Exec-timeout value invalid\n");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(1);
|
||||
break;
|
||||
|
@ -515,6 +593,10 @@ int main(int argc, char **argv, char **env)
|
|||
return (vtysh_mark_file(inputfile));
|
||||
}
|
||||
|
||||
/* Allow command-line control of timeout */
|
||||
if (exec_timeout > 0)
|
||||
vtysh_exec_timeout_config(exec_timeout);
|
||||
|
||||
/* Start execution only if not in dry-run mode */
|
||||
if (dryrun && !cmd) {
|
||||
if (inputfile) {
|
||||
|
|
Loading…
Reference in a new issue