aboutsummaryrefslogtreecommitdiffstats
path: root/src/vty
diff options
context:
space:
mode:
Diffstat (limited to 'src/vty')
-rw-r--r--src/vty/command.c146
-rw-r--r--src/vty/cpu_sched_vty.c10
-rw-r--r--src/vty/logging_vty.c65
3 files changed, 188 insertions, 33 deletions
diff --git a/src/vty/command.c b/src/vty/command.c
index d8649f58..b38be34e 100644
--- a/src/vty/command.c
+++ b/src/vty/command.c
@@ -624,7 +624,7 @@ typedef int (*print_func_t)(void *data, const char *fmt, ...);
static const struct value_string cmd_attr_desc[] = {
{ CMD_ATTR_DEPRECATED, "This command is deprecated" },
- { CMD_ATTR_HIDDEN, "This command is hidden" },
+ { CMD_ATTR_HIDDEN, "This command is hidden (check expert mode)" },
{ CMD_ATTR_IMMEDIATE, "This command applies immediately" },
{ CMD_ATTR_NODE_EXIT, "This command applies on VTY node exit" },
/* CMD_ATTR_LIB_COMMAND is intentionally skipped */
@@ -633,12 +633,14 @@ static const struct value_string cmd_attr_desc[] = {
/* Public attributes (to be printed in the VTY / XML reference) */
#define CMD_ATTR_PUBLIC_MASK \
- (CMD_ATTR_IMMEDIATE | CMD_ATTR_NODE_EXIT)
+ (CMD_ATTR_HIDDEN | CMD_ATTR_IMMEDIATE | CMD_ATTR_NODE_EXIT)
/* Get a flag character for a global VTY command attribute */
static char cmd_attr_get_flag(unsigned int attr)
{
switch (attr) {
+ case CMD_ATTR_HIDDEN:
+ return '^';
case CMD_ATTR_IMMEDIATE:
return '!';
case CMD_ATTR_NODE_EXIT:
@@ -672,7 +674,8 @@ static const char cmd_lib_attr_letters[32] = {
/*
* Write one cmd_element as XML via a print_func_t.
*/
-static int vty_dump_element(struct cmd_element *cmd, print_func_t print_func, void *data, const char *newline)
+static int vty_dump_element(const struct cmd_element *cmd, print_func_t print_func,
+ void *data, const char *newline)
{
char *xml_string = xml_escape(cmd->string);
unsigned int i;
@@ -766,12 +769,27 @@ static int vty_dump_element(struct cmd_element *cmd, print_func_t print_func, vo
return 0;
}
-static bool vty_command_is_common(struct cmd_element *cmd);
+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;
@@ -784,27 +802,27 @@ static int vty_dump_nodes(print_func_t print_func, void *data, const char *newli
print_func(data, " <description>These commands are available on all VTY nodes. They are listed"
" here only once, to unclutter the VTY reference.</description>%s", newline);
for (i = 0; i < vector_active(cmdvec); ++i) {
- struct cmd_node *cnode;
- cnode = vector_slot(cmdvec, i);
+ const struct cmd_node *cnode = vector_slot(cmdvec, i);
if (!cnode)
continue;
if (cnode->node != CONFIG_NODE)
continue;
for (j = 0; j < vector_active(cnode->cmd_vector); ++j) {
- struct cmd_element *elem;
- elem = vector_slot(cnode->cmd_vector, j);
+ const struct cmd_element *elem = vector_slot(cnode->cmd_vector, j);
if (!vty_command_is_common(elem))
continue;
- if (!(elem->attr & (CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN)))
- vty_dump_element(elem, print_func, data, newline);
+ if (!match && (elem->attr & gflag_mask) != 0x00)
+ continue;
+ if (match && (elem->attr & gflag_mask) == 0x00)
+ continue;
+ vty_dump_element(elem, print_func, data, newline);
}
}
print_func(data, " </node>%s", newline);
for (i = 0; i < vector_active(cmdvec); ++i) {
- struct cmd_node *cnode;
- cnode = vector_slot(cmdvec, i);
+ const struct cmd_node *cnode = vector_slot(cmdvec, i);
if (!cnode)
continue;
if (vector_active(cnode->cmd_vector) < 1)
@@ -815,8 +833,7 @@ static int vty_dump_nodes(print_func_t print_func, void *data, const char *newli
* 'name', the second becomes 'name_2', then 'name_3', ... */
same_name_count = 1;
for (j = 0; j < i; ++j) {
- struct cmd_node *cnode2;
- cnode2 = vector_slot(cmdvec, j);
+ const struct cmd_node *cnode2 = vector_slot(cmdvec, j);
if (!cnode2)
continue;
if (strcmp(cnode->name, cnode2->name) == 0)
@@ -830,12 +847,14 @@ static int vty_dump_nodes(print_func_t print_func, void *data, const char *newli
print_func(data, " <name>%s</name>%s", cnode->name, newline);
for (j = 0; j < vector_active(cnode->cmd_vector); ++j) {
- struct cmd_element *elem;
- elem = vector_slot(cnode->cmd_vector, j);
+ const struct cmd_element *elem = vector_slot(cnode->cmd_vector, j);
if (vty_command_is_common(elem))
continue;
- if (!(elem->attr & (CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN)))
- vty_dump_element(elem, print_func, data, newline);
+ if (!match && (elem->attr & gflag_mask) != 0x00)
+ continue;
+ if (match && (elem->attr & gflag_mask) == 0x00)
+ continue;
+ vty_dump_element(elem, print_func, data, newline);
}
print_func(data, " </node>%s", newline);
@@ -859,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, ...)
@@ -872,11 +894,61 @@ static int print_func_stream(void *data, const char *format, ...)
return rc;
}
+const struct value_string vty_ref_gen_mode_names[] = {
+ { VTY_REF_GEN_MODE_DEFAULT, "default" },
+ { VTY_REF_GEN_MODE_EXPERT, "expert" },
+ { VTY_REF_GEN_MODE_HIDDEN, "hidden" },
+ { 0, NULL }
+};
+
+const struct value_string vty_ref_gen_mode_desc[] = {
+ { VTY_REF_GEN_MODE_DEFAULT, "all commands except deprecated and hidden" },
+ { VTY_REF_GEN_MODE_EXPERT, "all commands including hidden, excluding deprecated" },
+ { VTY_REF_GEN_MODE_HIDDEN, "hidden commands only" },
+ { 0, NULL }
+};
+
+/*! Print the XML reference of all VTY nodes to the given stream.
+ * \param[out] stream Output stream to print the XML reference to.
+ * \param[in] mode The XML reference generation mode.
+ * \returns always 0 for now, no errors possible.
+ */
+int vty_dump_xml_ref_mode(FILE *stream, enum vty_ref_gen_mode mode)
+{
+ unsigned char gflag_mask;
+ bool match = false;
+
+ switch (mode) {
+ case VTY_REF_GEN_MODE_EXPERT:
+ /* All commands except deprecated */
+ gflag_mask = CMD_ATTR_DEPRECATED;
+ break;
+ case VTY_REF_GEN_MODE_HIDDEN:
+ /* Only hidden commands */
+ gflag_mask = CMD_ATTR_HIDDEN;
+ match = true;
+ break;
+ case VTY_REF_GEN_MODE_DEFAULT:
+ default:
+ /* All commands except deprecated and hidden */
+ gflag_mask = CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN;
+ break;
+ }
+
+ return vty_dump_nodes(print_func_stream, stream, "\n", gflag_mask, match);
+}
+
/*! Print the XML reference of all VTY nodes to the given stream.
+ * \param[out] stream Output stream to print the XML reference to.
+ * \returns always 0 for now, no errors possible.
+ *
+ * NOTE: this function is deprecated because it does not allow to
+ * specify the XML reference generation mode (default mode
+ * is hard-coded). Use vty_dump_xml_ref_mode() instead.
*/
int vty_dump_xml_ref(FILE *stream)
{
- return vty_dump_nodes(print_func_stream, stream, "\n");
+ return vty_dump_xml_ref_mode(stream, VTY_REF_GEN_MODE_DEFAULT);
}
/* Check if a command with given string exists at given node */
@@ -2007,7 +2079,9 @@ cmd_describe_command_real(vector vline, struct vty *vty, int *status)
if (!cmd_element)
continue;
- if (cmd_element->attr & (CMD_ATTR_DEPRECATED|CMD_ATTR_HIDDEN))
+ if (cmd_element->attr & CMD_ATTR_DEPRECATED)
+ continue;
+ if (!vty->expert_mode && (cmd_element->attr & CMD_ATTR_HIDDEN))
continue;
strvec = cmd_element->strvec;
@@ -2867,7 +2941,10 @@ DEFUN(config_terminal,
}
/* Enable command */
-DEFUN(enable, config_enable_cmd, "enable", "Turn on privileged mode command\n")
+DEFUN(enable, config_enable_cmd,
+ "enable [expert-mode]",
+ "Turn on privileged mode command\n"
+ "Enable the expert mode (show hidden commands)\n")
{
/* If enable password is NULL, change to ENABLE_NODE */
if ((host.enable == NULL && host.enable_encrypt == NULL) ||
@@ -2876,6 +2953,8 @@ DEFUN(enable, config_enable_cmd, "enable", "Turn on privileged mode command\n")
else
vty->node = AUTH_ENABLE_NODE;
+ vty->expert_mode = argc > 0;
+
return CMD_SUCCESS;
}
@@ -2885,6 +2964,9 @@ DEFUN(disable,
{
if (vty->node == ENABLE_NODE)
vty->node = VIEW_NODE;
+
+ vty->expert_mode = false;
+
return CMD_SUCCESS;
}
@@ -3071,7 +3153,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;
@@ -3083,7 +3165,9 @@ static unsigned int node_flag_mask(const struct cmd_node *cnode)
if ((cmd = vector_slot(cnode->cmd_vector, i)) == NULL)
continue;
- if (cmd->attr & (CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN))
+ if (cmd->attr & CMD_ATTR_DEPRECATED)
+ continue;
+ if (!expert_mode && (cmd->attr & CMD_ATTR_HIDDEN))
continue;
if (~cmd->usrattr & ((unsigned)1 << f))
continue;
@@ -3111,7 +3195,9 @@ static const char *cmd_gflag_mask(const struct cmd_element *cmd)
char *ptr = &char_mask[0];
/* Mutually exclusive global attributes */
- if (cmd->attr & CMD_ATTR_IMMEDIATE)
+ if (cmd->attr & CMD_ATTR_HIDDEN)
+ *(ptr++) = cmd_attr_get_flag(CMD_ATTR_HIDDEN);
+ else if (cmd->attr & CMD_ATTR_IMMEDIATE)
*(ptr++) = cmd_attr_get_flag(CMD_ATTR_IMMEDIATE);
else if (cmd->attr & CMD_ATTR_NODE_EXIT)
*(ptr++) = cmd_attr_get_flag(CMD_ATTR_NODE_EXIT);
@@ -3165,12 +3251,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 | CMD_ATTR_HIDDEN))
+ if (cmd->attr & CMD_ATTR_DEPRECATED)
+ continue;
+ if (!vty->expert_mode && (cmd->attr & CMD_ATTR_HIDDEN))
continue;
if (!argc)
vty_out(vty, " %s%s", cmd->string, VTY_NEWLINE);
@@ -4171,7 +4259,7 @@ static void install_basic_node_commands(int node)
/*! Return true if a node is installed by install_basic_node_commands(), so
* that we can avoid repeating them for each and every node during 'show
* running-config' */
-static bool vty_command_is_common(struct cmd_element *cmd)
+static bool vty_command_is_common(const struct cmd_element *cmd)
{
if (cmd == &config_help_cmd
|| cmd == &show_vty_attr_all_cmd
diff --git a/src/vty/cpu_sched_vty.c b/src/vty/cpu_sched_vty.c
index 0b72abb5..4ccc6274 100644
--- a/src/vty/cpu_sched_vty.c
+++ b/src/vty/cpu_sched_vty.c
@@ -371,7 +371,7 @@ static int my_sched_setaffinity(enum sched_vty_thread_id tid_type, pid_t pid,
}
-DEFUN(cfg_sched_cpu_affinity, cfg_sched_cpu_affinity_cmd,
+DEFUN_ATTR(cfg_sched_cpu_affinity, cfg_sched_cpu_affinity_cmd,
"cpu-affinity (self|all|<0-4294967295>|THREADNAME) CPUHEXMASK [delay]",
"Set CPU affinity mask on a (group of) thread(s)\n"
"Set CPU affinity mask on thread running the VTY\n"
@@ -379,7 +379,8 @@ DEFUN(cfg_sched_cpu_affinity, cfg_sched_cpu_affinity_cmd,
"Set CPU affinity mask on a thread with specified PID\n"
"Set CPU affinity mask on a thread with specified thread name\n"
"CPU affinity mask\n"
- "If set, delay applying the affinity mask now and let the app handle it at a later point\n")
+ "If set, delay applying the affinity mask now and let the app handle it at a later point\n",
+ CMD_ATTR_IMMEDIATE)
{
const char* str_who = argv[0];
const char *str_mask = argv[1];
@@ -476,11 +477,12 @@ static int set_sched_rr(unsigned int prio)
return 0;
}
-DEFUN(cfg_sched_policy, cfg_sched_policy_cmd,
+DEFUN_ATTR(cfg_sched_policy, cfg_sched_policy_cmd,
"policy rr <1-32>",
"Set the scheduling policy to use for the process\n"
"Use the SCHED_RR real-time scheduling algorithm\n"
- "Set the SCHED_RR real-time priority\n")
+ "Set the SCHED_RR real-time priority\n",
+ CMD_ATTR_IMMEDIATE)
{
sched_vty_opts->sched_rr_prio = atoi(argv[0]);
diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c
index 200b45a1..02823504 100644
--- a/src/vty/logging_vty.c
+++ b/src/vty/logging_vty.c
@@ -732,6 +732,64 @@ DEFUN(cfg_no_log_syslog, cfg_no_log_syslog_cmd,
}
#endif /* HAVE_SYSLOG_H */
+DEFUN(cfg_log_systemd_journal, cfg_log_systemd_journal_cmd,
+ "log systemd-journal [raw]",
+ LOG_STR "Logging to systemd-journal\n"
+ "Offload rendering of the meta information (location, category) to systemd\n")
+{
+#ifdef ENABLE_SYSTEMD_LOGGING
+ struct log_target *tgt;
+ bool raw = argc > 0;
+
+ log_tgt_mutex_lock();
+ tgt = log_target_find(LOG_TGT_TYPE_SYSTEMD, NULL);
+ if (tgt == NULL) {
+ tgt = log_target_create_systemd(raw);
+ if (tgt == NULL) {
+ vty_out(vty, "%% Unable to create systemd-journal "
+ "log target%s", VTY_NEWLINE);
+ RET_WITH_UNLOCK(CMD_WARNING);
+ }
+ log_add_target(tgt);
+ } else if (tgt->sd_journal.raw != raw) {
+ log_target_systemd_set_raw(tgt, raw);
+ }
+
+ vty->index = tgt;
+ vty->node = CFG_LOG_NODE;
+
+ RET_WITH_UNLOCK(CMD_SUCCESS);
+#else
+ vty_out(vty, "%% systemd-journal logging is not available "
+ "in this build of libosmocore%s", VTY_NEWLINE);
+ return CMD_WARNING;
+#endif /* ENABLE_SYSTEMD_LOGGING */
+}
+
+DEFUN(cfg_no_log_systemd_journal, cfg_no_log_systemd_journal_cmd,
+ "no log systemd-journal",
+ NO_STR LOG_STR "Logging to systemd-journal\n")
+{
+#ifdef ENABLE_SYSTEMD_LOGGING
+ struct log_target *tgt;
+
+ log_tgt_mutex_lock();
+ tgt = log_target_find(LOG_TGT_TYPE_SYSTEMD, NULL);
+ if (!tgt) {
+ vty_out(vty, "%% No systemd-journal logging active%s", VTY_NEWLINE);
+ RET_WITH_UNLOCK(CMD_WARNING);
+ }
+
+ log_target_destroy(tgt);
+
+ RET_WITH_UNLOCK(CMD_SUCCESS);
+#else
+ vty_out(vty, "%% systemd-journal logging is not available "
+ "in this build of libosmocore%s", VTY_NEWLINE);
+ return CMD_WARNING;
+#endif /* ENABLE_SYSTEMD_LOGGING */
+}
+
DEFUN(cfg_log_gsmtap, cfg_log_gsmtap_cmd,
"log gsmtap [HOSTNAME]",
LOG_STR "Logging via GSMTAP\n"
@@ -926,6 +984,11 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt)
vty_out(vty, "log gsmtap %s%s",
tgt->tgt_gsmtap.hostname, VTY_NEWLINE);
break;
+ case LOG_TGT_TYPE_SYSTEMD:
+ vty_out(vty, "log systemd-journal%s%s",
+ tgt->sd_journal.raw ? " raw" : "",
+ VTY_NEWLINE);
+ break;
}
vty_out(vty, " logging filter all %u%s",
@@ -1127,5 +1190,7 @@ void logging_vty_add_cmds()
install_lib_element(CONFIG_NODE, &cfg_log_syslog_local_cmd);
install_lib_element(CONFIG_NODE, &cfg_no_log_syslog_cmd);
#endif
+ install_lib_element(CONFIG_NODE, &cfg_log_systemd_journal_cmd);
+ install_lib_element(CONFIG_NODE, &cfg_no_log_systemd_journal_cmd);
install_lib_element(CONFIG_NODE, &cfg_log_gsmtap_cmd);
}