aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <vyanitskiy@sysmocom.de>2020-10-25 16:34:57 +0700
committerVadim Yanitskiy <vyanitskiy@sysmocom.de>2020-10-25 16:52:42 +0700
commit0a2d9bdfae78c9bfddc8cc838abaddc508f210f1 (patch)
tree11dd91497559a8f7540d4dca7177c95d340f2280
parentf36b76211f8bae3f372f7202827a718e125706f1 (diff)
vty/command: fix: restrict the expert mode to the current sessionHEADmaster
Having the expert mode flag stored in the global 'host' structure was a bad idea, because this way it applies globally. In other words, if user Bob activates the expert mode in his dedicated session (e.g. a telnet connection), then not only him, but all other users would see the hidden commands in their VTYs. Moreover, if somebody deactivates the expert mode, it would also affect the Bob's VTY session. And finally, terminating a VTY session would not deactivate the expert mode. Let's move that flag from the global 'struct host' to 'struct vty' representing an individual VTY session, so then the expert mode would only affect the session where it was activated. In functions related to the XML VTY reference generation we don't have access to 'struct vty' (there may be no VTY session at all). Add two additional arguments to vty_dump_nodes(), indicating the global flag mask and a matching mode. This would allow to match the VTY commands in many different ways, e.g. one can dump hidden commands only, or all commands except the library specific ones. Change-Id: Iba13f0949061e3dadf9cf92829d15e97074fe4ad Related: SYS#4910
-rw-r--r--include/osmocom/vty/command.h3
-rw-r--r--include/osmocom/vty/vty.h3
-rw-r--r--src/vty/command.c55
3 files changed, 41 insertions, 20 deletions
diff --git a/include/osmocom/vty/command.h b/include/osmocom/vty/command.h
index eb7ee35e..b6088482 100644
--- a/include/osmocom/vty/command.h
+++ b/include/osmocom/vty/command.h
@@ -67,9 +67,6 @@ struct host {
/*! VTY application information */
const struct vty_app_info *app_info;
-
- /*! Whether the expert mode is enabled. */
- bool expert_mode;
};
/*! There are some command levels which called from command node. */
diff --git a/include/osmocom/vty/vty.h b/include/osmocom/vty/vty.h
index 6a82d7e3..d34433fa 100644
--- a/include/osmocom/vty/vty.h
+++ b/include/osmocom/vty/vty.h
@@ -165,6 +165,9 @@ struct vty {
/*! When reading from a config file, these are the indenting characters expected for children of
* the current VTY node. */
char *indent;
+
+ /*! Whether the expert mode is enabled. */
+ bool expert_mode;
};
/* Small macro to determine newline is newline only or linefeed needed. */
diff --git a/src/vty/command.c b/src/vty/command.c
index 7ea19712..c233aa6a 100644
--- a/src/vty/command.c
+++ b/src/vty/command.c
@@ -773,8 +773,23 @@ static bool vty_command_is_common(const struct cmd_element *cmd);
/*
* Dump all nodes and commands associated with a given node as XML via a print_func_t.
+ *
+ * (gflag_mask, match = false) - print only those commands with non-matching flags.
+ * (gflag_mask, match = true) - print only those commands with matching flags.
+ *
+ * Some examples:
+ *
+ * Print all commands except deprecated and hidden (default mode):
+ * (CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN, false)
+ * Print only deprecated and hidden commands:
+ * (CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN, true)
+ * Print all commands except deprecated (expert mode):
+ * (CMD_ATTR_DEPRECATED, false)
+ * Print only hidden commands:
+ * (CMD_ATTR_HIDDEN, true)
*/
-static int vty_dump_nodes(print_func_t print_func, void *data, const char *newline)
+static int vty_dump_nodes(print_func_t print_func, void *data, const char *newline,
+ unsigned char gflag_mask, bool match)
{
int i, j;
int same_name_count;
@@ -797,9 +812,9 @@ static int vty_dump_nodes(print_func_t print_func, void *data, const char *newli
const struct cmd_element *elem = vector_slot(cnode->cmd_vector, j);
if (!vty_command_is_common(elem))
continue;
- if (elem->attr & CMD_ATTR_DEPRECATED)
+ if (!match && (elem->attr & gflag_mask) != 0x00)
continue;
- if (!host.expert_mode && (elem->attr & CMD_ATTR_HIDDEN))
+ if (match && (elem->attr & gflag_mask) == 0x00)
continue;
vty_dump_element(elem, print_func, data, newline);
}
@@ -835,9 +850,9 @@ static int vty_dump_nodes(print_func_t print_func, void *data, const char *newli
const struct cmd_element *elem = vector_slot(cnode->cmd_vector, j);
if (vty_command_is_common(elem))
continue;
- if (elem->attr & CMD_ATTR_DEPRECATED)
+ if (!match && (elem->attr & gflag_mask) != 0x00)
continue;
- if (!host.expert_mode && (elem->attr & CMD_ATTR_HIDDEN))
+ if (match && (elem->attr & gflag_mask) == 0x00)
continue;
vty_dump_element(elem, print_func, data, newline);
}
@@ -863,7 +878,10 @@ static int print_func_vty(void *data, const char *format, ...)
static int vty_dump_xml_ref_to_vty(struct vty *vty)
{
- return vty_dump_nodes(print_func_vty, vty, VTY_NEWLINE);
+ unsigned char gflag_mask = CMD_ATTR_DEPRECATED;
+ if (!vty->expert_mode)
+ gflag_mask |= CMD_ATTR_HIDDEN;
+ return vty_dump_nodes(print_func_vty, vty, VTY_NEWLINE, gflag_mask, false);
}
static int print_func_stream(void *data, const char *format, ...)
@@ -895,17 +913,21 @@ const struct value_string vty_ref_gen_mode_desc[] = {
*/
int vty_dump_xml_ref_mode(FILE *stream, enum vty_ref_gen_mode mode)
{
+ unsigned char gflag_mask;
+
switch (mode) {
case VTY_REF_GEN_MODE_EXPERT:
- host.expert_mode = true;
+ /* All commands except deprecated */
+ gflag_mask = CMD_ATTR_DEPRECATED;
break;
case VTY_REF_GEN_MODE_DEFAULT:
default:
- host.expert_mode = false;
+ /* All commands except deprecated and hidden */
+ gflag_mask = CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN;
break;
}
- return vty_dump_nodes(print_func_stream, stream, "\n");
+ return vty_dump_nodes(print_func_stream, stream, "\n", gflag_mask, false);
}
/*! Print the XML reference of all VTY nodes to the given stream.
@@ -2051,7 +2073,7 @@ cmd_describe_command_real(vector vline, struct vty *vty, int *status)
if (cmd_element->attr & CMD_ATTR_DEPRECATED)
continue;
- if (!host.expert_mode && (cmd_element->attr & CMD_ATTR_HIDDEN))
+ if (!vty->expert_mode && (cmd_element->attr & CMD_ATTR_HIDDEN))
continue;
strvec = cmd_element->strvec;
@@ -2923,7 +2945,7 @@ DEFUN(enable, config_enable_cmd,
else
vty->node = AUTH_ENABLE_NODE;
- host.expert_mode = argc > 0;
+ vty->expert_mode = argc > 0;
return CMD_SUCCESS;
}
@@ -2935,7 +2957,7 @@ DEFUN(disable,
if (vty->node == ENABLE_NODE)
vty->node = VIEW_NODE;
- host.expert_mode = false;
+ vty->expert_mode = false;
return CMD_SUCCESS;
}
@@ -3123,7 +3145,7 @@ gDEFUN(show_vty_attr, show_vty_attr_cmd,
}
/* Compose flag bit-mask for all commands within the given node */
-static unsigned int node_flag_mask(const struct cmd_node *cnode)
+static unsigned int node_flag_mask(const struct cmd_node *cnode, bool expert_mode)
{
unsigned int flag_mask = 0x00;
unsigned int f, i;
@@ -3137,7 +3159,7 @@ static unsigned int node_flag_mask(const struct cmd_node *cnode)
continue;
if (cmd->attr & CMD_ATTR_DEPRECATED)
continue;
- if (!host.expert_mode && (cmd->attr & CMD_ATTR_HIDDEN))
+ if (!expert_mode && (cmd->attr & CMD_ATTR_HIDDEN))
continue;
if (~cmd->usrattr & ((unsigned)1 << f))
continue;
@@ -3221,14 +3243,14 @@ gDEFUN(config_list, config_list_cmd,
struct cmd_element *cmd;
if (argc > 0)
- flag_mask = node_flag_mask(cnode);
+ flag_mask = node_flag_mask(cnode, vty->expert_mode);
for (i = 0; i < vector_active(cnode->cmd_vector); i++) {
if ((cmd = vector_slot(cnode->cmd_vector, i)) == NULL)
continue;
if (cmd->attr & CMD_ATTR_DEPRECATED)
continue;
- if (!host.expert_mode && (cmd->attr & CMD_ATTR_HIDDEN))
+ if (!vty->expert_mode && (cmd->attr & CMD_ATTR_HIDDEN))
continue;
if (!argc)
vty_out(vty, " %s%s", cmd->string, VTY_NEWLINE);
@@ -4302,7 +4324,6 @@ void cmd_init(int terminal)
host.lines = -1;
host.motd = default_motd;
host.motdfile = NULL;
- host.expert_mode = false;
/* Install top nodes. */
install_node_bare(&view_node, NULL);