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)
.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};
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,
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);
return host.domainname;
}
+static int root_on_exit(struct vty *vty);
+
/* Standard command node structures. */
static struct cmd_node auth_node = {
.name = "auth",
.name = "view",
.node = VIEW_NODE,
.prompt = "%s> ",
+ .node_exit = root_on_exit,
};
static struct cmd_node auth_enable_node = {
.name = "enable",
.node = ENABLE_NODE,
.prompt = "%s# ",
+ .node_exit = root_on_exit,
};
static int config_write_host(struct vty *vty);
.parent_node = ENABLE_NODE,
.prompt = "%s(config)# ",
.config_write = config_write_host,
+ .node_exit = vty_config_node_exit,
};
static const struct facility_map {
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--;
}
/* 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;
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);
list_delete(&vty->error);
}
- /* Check configure. */
- vty_config_exit(vty);
-
/* OK free vty. */
XFREE(MTYPE_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) {
}
vty->config = false;
+ return 1;
}
/* Master of the threads. */
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 *);