mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-02 22:09:48 +00:00
*: add ->node_exit to struct cmd_node
Rather than doing a f*gly hack for the RPKI code, let's do an on-exit hook in cmd_node. Also allows replacing some special-casing in the vty code. Signed-off-by: David Lamparter <equinox@diac24.net>
This commit is contained in:
parent
893d8beb4d
commit
791ded4a62
@ -104,7 +104,7 @@ static struct rtr_mgr_group *get_connected_group(void);
|
||||
static void print_prefix_table(struct vty *vty);
|
||||
static void install_cli_commands(void);
|
||||
static int config_write(struct vty *vty);
|
||||
static void overwrite_exit_commands(void);
|
||||
static int config_on_exit(struct vty *vty);
|
||||
static void free_cache(struct cache *cache);
|
||||
static struct rtr_mgr_group *get_groups(void);
|
||||
#if defined(FOUND_SSH)
|
||||
@ -149,6 +149,7 @@ static struct cmd_node rpki_node = {
|
||||
.parent_node = CONFIG_NODE,
|
||||
.prompt = "%s(config-rpki)# ",
|
||||
.config_write = config_write,
|
||||
.node_exit = config_on_exit,
|
||||
};
|
||||
static const struct route_map_rule_cmd route_match_rpki_cmd = {
|
||||
"rpki", route_match, route_match_compile, route_match_free};
|
||||
@ -1400,35 +1401,10 @@ DEFUN (show_rpki_cache_connection,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN_NOSH (rpki_exit,
|
||||
rpki_exit_cmd,
|
||||
"exit",
|
||||
"Exit rpki configuration and restart rpki session\n")
|
||||
static int config_on_exit(struct vty *vty)
|
||||
{
|
||||
reset(false);
|
||||
|
||||
vty->node = CONFIG_NODE;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN_NOSH (rpki_quit,
|
||||
rpki_quit_cmd,
|
||||
"quit",
|
||||
"Exit rpki configuration mode\n")
|
||||
{
|
||||
return rpki_exit(self, vty, argc, argv);
|
||||
}
|
||||
|
||||
DEFUN_NOSH (rpki_end,
|
||||
rpki_end_cmd,
|
||||
"end",
|
||||
"End rpki configuration, restart rpki session and change to enable mode.\n")
|
||||
{
|
||||
int ret = reset(false);
|
||||
|
||||
vty_config_exit(vty);
|
||||
vty->node = ENABLE_NODE;
|
||||
return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
|
||||
return 1;
|
||||
}
|
||||
|
||||
DEFUN (rpki_reset,
|
||||
@ -1522,32 +1498,11 @@ DEFUN (no_match_rpki,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void overwrite_exit_commands(void)
|
||||
{
|
||||
unsigned int i;
|
||||
vector cmd_vector = rpki_node.cmd_vector;
|
||||
|
||||
for (i = 0; i < cmd_vector->active; ++i) {
|
||||
struct cmd_element *cmd = vector_lookup(cmd_vector, i);
|
||||
|
||||
if (strcmp(cmd->string, "exit") == 0
|
||||
|| strcmp(cmd->string, "quit") == 0
|
||||
|| strcmp(cmd->string, "end") == 0) {
|
||||
uninstall_element(RPKI_NODE, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
install_element(RPKI_NODE, &rpki_exit_cmd);
|
||||
install_element(RPKI_NODE, &rpki_quit_cmd);
|
||||
install_element(RPKI_NODE, &rpki_end_cmd);
|
||||
}
|
||||
|
||||
static void install_cli_commands(void)
|
||||
{
|
||||
// TODO: make config write work
|
||||
install_node(&rpki_node);
|
||||
install_default(RPKI_NODE);
|
||||
overwrite_exit_commands();
|
||||
install_element(CONFIG_NODE, &rpki_cmd);
|
||||
install_element(ENABLE_NODE, &rpki_cmd);
|
||||
|
||||
|
@ -99,6 +99,8 @@ const char *cmd_domainname_get(void)
|
||||
return host.domainname;
|
||||
}
|
||||
|
||||
static int root_on_exit(struct vty *vty);
|
||||
|
||||
/* Standard command node structures. */
|
||||
static struct cmd_node auth_node = {
|
||||
.name = "auth",
|
||||
@ -110,6 +112,7 @@ static struct cmd_node view_node = {
|
||||
.name = "view",
|
||||
.node = VIEW_NODE,
|
||||
.prompt = "%s> ",
|
||||
.node_exit = root_on_exit,
|
||||
};
|
||||
|
||||
static struct cmd_node auth_enable_node = {
|
||||
@ -122,6 +125,7 @@ static struct cmd_node enable_node = {
|
||||
.name = "enable",
|
||||
.node = ENABLE_NODE,
|
||||
.prompt = "%s# ",
|
||||
.node_exit = root_on_exit,
|
||||
};
|
||||
|
||||
static int config_write_host(struct vty *vty);
|
||||
@ -131,6 +135,7 @@ static struct cmd_node config_node = {
|
||||
.parent_node = ENABLE_NODE,
|
||||
.prompt = "%s(config)# ",
|
||||
.config_write = config_write_host,
|
||||
.node_exit = vty_config_node_exit,
|
||||
};
|
||||
|
||||
static const struct facility_map {
|
||||
@ -1382,28 +1387,25 @@ DEFUN (config_exit,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int root_on_exit(struct vty *vty)
|
||||
{
|
||||
if (vty_shell(vty))
|
||||
exit(0);
|
||||
else
|
||||
vty->status = VTY_CLOSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cmd_exit(struct vty *vty)
|
||||
{
|
||||
struct cmd_node *cnode = vector_lookup(cmdvec, vty->node);
|
||||
|
||||
switch (vty->node) {
|
||||
case VIEW_NODE:
|
||||
case ENABLE_NODE:
|
||||
if (vty_shell(vty))
|
||||
exit(0);
|
||||
else
|
||||
vty->status = VTY_CLOSE;
|
||||
break;
|
||||
case CONFIG_NODE:
|
||||
vty->node = ENABLE_NODE;
|
||||
vty_config_exit(vty);
|
||||
break;
|
||||
default:
|
||||
if (cnode->parent_node)
|
||||
vty->node = cnode->parent_node;
|
||||
break;
|
||||
if (cnode->node_exit) {
|
||||
if (!cnode->node_exit(vty))
|
||||
return;
|
||||
}
|
||||
|
||||
if (cnode->parent_node)
|
||||
vty->node = cnode->parent_node;
|
||||
if (vty->xpath_index > 0)
|
||||
vty->xpath_index--;
|
||||
}
|
||||
|
@ -182,6 +182,11 @@ struct cmd_node {
|
||||
/* Node's configuration write function */
|
||||
int (*config_write)(struct vty *);
|
||||
|
||||
/* called when leaving the node on a VTY session.
|
||||
* return 1 if normal exit processing should happen, 0 to suppress
|
||||
*/
|
||||
int (*node_exit)(struct vty *);
|
||||
|
||||
/* Node's command graph */
|
||||
struct graph *cmdgraph;
|
||||
|
||||
|
19
lib/vty.c
19
lib/vty.c
@ -2199,6 +2199,9 @@ void vty_close(struct vty *vty)
|
||||
int i;
|
||||
bool was_stdio = false;
|
||||
|
||||
/* Drop out of configure / transaction if needed. */
|
||||
vty_config_exit(vty);
|
||||
|
||||
/* Cancel threads.*/
|
||||
THREAD_OFF(vty->t_read);
|
||||
THREAD_OFF(vty->t_write);
|
||||
@ -2242,9 +2245,6 @@ void vty_close(struct vty *vty)
|
||||
list_delete(&vty->error);
|
||||
}
|
||||
|
||||
/* Check configure. */
|
||||
vty_config_exit(vty);
|
||||
|
||||
/* OK free vty. */
|
||||
XFREE(MTYPE_VTY, vty);
|
||||
|
||||
@ -2614,14 +2614,18 @@ void vty_config_exit(struct vty *vty)
|
||||
cnode = vector_lookup(cmdvec, node);
|
||||
node = cnode->parent_node;
|
||||
}
|
||||
if (node != CONFIG_NODE) {
|
||||
vty_out(vty,
|
||||
"WARNING: vty_config_exit() from outside CONFIG_NODE!\n");
|
||||
if (node != CONFIG_NODE)
|
||||
/* called outside config, e.g. vty_close() in ENABLE_NODE */
|
||||
return;
|
||||
}
|
||||
|
||||
while (vty->node != ENABLE_NODE)
|
||||
/* will call vty_config_node_exit() below */
|
||||
cmd_exit(vty);
|
||||
}
|
||||
|
||||
int vty_config_node_exit(struct vty *vty)
|
||||
{
|
||||
vty->xpath_index = 0;
|
||||
|
||||
/* Check if there's a pending confirmed commit. */
|
||||
if (vty->t_confirmed_commit_timeout) {
|
||||
@ -2644,6 +2648,7 @@ void vty_config_exit(struct vty *vty)
|
||||
}
|
||||
|
||||
vty->config = false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Master of the threads. */
|
||||
|
@ -323,6 +323,7 @@ extern void vty_log(const char *level, const char *proto, const char *msg,
|
||||
extern int vty_config_enter(struct vty *vty, bool private_config,
|
||||
bool exclusive);
|
||||
extern void vty_config_exit(struct vty *);
|
||||
extern int vty_config_node_exit(struct vty *);
|
||||
extern int vty_shell(struct vty *);
|
||||
extern int vty_shell_serv(struct vty *);
|
||||
extern void vty_hello(struct vty *);
|
||||
|
Loading…
Reference in New Issue
Block a user