summaryrefslogtreecommitdiff
path: root/lib/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/command.c')
-rw-r--r--lib/command.c185
1 files changed, 142 insertions, 43 deletions
diff --git a/lib/command.c b/lib/command.c
index 10ab066bfb..e8ba637623 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -33,6 +33,11 @@ Boston, MA 02111-1307, USA. */
#include "command.h"
#include "workqueue.h"
#include "vrf.h"
+#include "qobj.h"
+
+DEFINE_MTYPE( LIB, HOST, "Host config")
+DEFINE_MTYPE( LIB, STRVEC, "String vector")
+DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command desc")
/* Command vector which includes some level of command lists. Normally
each daemon maintains each own cmdvec. */
@@ -92,12 +97,6 @@ static struct cmd_node view_node =
"%s> ",
};
-static struct cmd_node restricted_node =
-{
- RESTRICTED_NODE,
- "%s$ ",
-};
-
static struct cmd_node auth_enable_node =
{
AUTH_ENABLE_NODE,
@@ -225,6 +224,18 @@ argv_concat (const char **argv, int argc, int shift)
return str;
}
+static unsigned int
+cmd_hash_key (void *p)
+{
+ return (uintptr_t) p;
+}
+
+static int
+cmd_hash_cmp (const void *a, const void *b)
+{
+ return a == b;
+}
+
/* Install top node of command vector. */
void
install_node (struct cmd_node *node,
@@ -233,6 +244,7 @@ install_node (struct cmd_node *node,
vector_set_index (cmdvec, node->node, node);
node->func = func;
node->cmd_vector = vector_init (VECTOR_MIN_SIZE);
+ node->cmd_hash = hash_create (cmd_hash_key, cmd_hash_cmp);
}
/* Breaking up string into each command piece. I assume given
@@ -705,7 +717,11 @@ install_element (enum node_type ntype, struct cmd_element *cmd)
/* cmd_init hasn't been called */
if (!cmdvec)
- return;
+ {
+ fprintf (stderr, "%s called before cmd_init, breakage likely\n",
+ __func__);
+ return;
+ }
cnode = vector_slot (cmdvec, ntype);
@@ -715,10 +731,23 @@ install_element (enum node_type ntype, struct cmd_element *cmd)
ntype);
exit (1);
}
-
+
+ if (hash_lookup (cnode->cmd_hash, cmd) != NULL)
+ {
+ fprintf (stderr,
+ "Multiple command installs to node %d of command:\n%s\n",
+ ntype, cmd->string);
+ return;
+ }
+
+ assert (hash_get (cnode->cmd_hash, cmd, hash_alloc_intern));
+
vector_set (cnode->cmd_vector, cmd);
if (cmd->tokens == NULL)
cmd->tokens = cmd_parse_format(cmd->string, cmd->doc);
+
+ if (ntype == VIEW_NODE)
+ install_element (ENABLE_NODE, cmd);
}
static const unsigned char itoa64[] =
@@ -2014,7 +2043,6 @@ cmd_try_do_shortcut (enum node_type node, char* first_word) {
node != VIEW_NODE &&
node != AUTH_ENABLE_NODE &&
node != ENABLE_NODE &&
- node != RESTRICTED_NODE &&
0 == strcmp( "do", first_word ) )
return 1;
return 0;
@@ -2416,8 +2444,11 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status, int islib
/* Only one matched */
if (vector_slot (matchvec, 1) == NULL)
{
- match_str = (char **) matchvec->index;
- vector_only_wrapper_free (matchvec);
+ size_t index_size = matchvec->alloced * sizeof (void *);
+ match_str = XMALLOC (MTYPE_TMP, index_size);
+ memcpy (match_str, matchvec->index, index_size);
+ vector_free (matchvec);
+
*status = CMD_COMPLETE_FULL_MATCH;
return match_str;
}
@@ -2459,8 +2490,11 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status, int islib
/* Make new matchvec. */
matchvec = vector_init (INIT_MATCHVEC_SIZE);
vector_set (matchvec, lcdstr);
- match_str = (char **) matchvec->index;
- vector_only_wrapper_free (matchvec);
+
+ size_t index_size = matchvec->alloced * sizeof (void *);
+ match_str = XMALLOC (MTYPE_TMP, index_size);
+ memcpy (match_str, matchvec->index, index_size);
+ vector_free (matchvec);
*status = CMD_COMPLETE_MATCH;
return match_str;
@@ -2528,6 +2562,9 @@ node_parent ( enum node_type node )
case BGP_VPNV6_NODE:
case BGP_ENCAP_NODE:
case BGP_ENCAPV6_NODE:
+ case BGP_VNC_DEFAULTS_NODE:
+ case BGP_VNC_NVE_GROUP_NODE:
+ case BGP_VNC_L2_GROUP_NODE:
case BGP_IPV4_NODE:
case BGP_IPV4M_NODE:
case BGP_IPV6_NODE:
@@ -2537,8 +2574,25 @@ node_parent ( enum node_type node )
case KEYCHAIN_KEY_NODE:
ret = KEYCHAIN_NODE;
break;
+ case LINK_PARAMS_NODE:
+ ret = INTERFACE_NODE;
+ break;
+ case LDP_IPV4_NODE:
+ case LDP_IPV6_NODE:
+ ret = LDP_NODE;
+ break;
+ case LDP_IPV4_IFACE_NODE:
+ ret = LDP_IPV4_NODE;
+ break;
+ case LDP_IPV6_IFACE_NODE:
+ ret = LDP_IPV6_NODE;
+ break;
+ case LDP_PSEUDOWIRE_NODE:
+ ret = LDP_L2VPN_NODE;
+ break;
default:
ret = CONFIG_NODE;
+ break;
}
return ret;
@@ -2887,7 +2941,6 @@ DEFUN (config_exit,
{
case VIEW_NODE:
case ENABLE_NODE:
- case RESTRICTED_NODE:
if (vty_shell (vty))
exit (0);
else
@@ -2898,6 +2951,7 @@ DEFUN (config_exit,
vty_config_unlock (vty);
break;
case INTERFACE_NODE:
+ case NS_NODE:
case VRF_NODE:
case ZEBRA_NODE:
case BGP_NODE:
@@ -2905,6 +2959,8 @@ DEFUN (config_exit,
case RIPNG_NODE:
case OSPF_NODE:
case OSPF6_NODE:
+ case LDP_NODE:
+ case LDP_L2VPN_NODE:
case ISIS_NODE:
case KEYCHAIN_NODE:
case MASC_NODE:
@@ -2919,13 +2975,32 @@ DEFUN (config_exit,
case BGP_VPNV6_NODE:
case BGP_ENCAP_NODE:
case BGP_ENCAPV6_NODE:
+ case BGP_VNC_DEFAULTS_NODE:
+ case BGP_VNC_NVE_GROUP_NODE:
+ case BGP_VNC_L2_GROUP_NODE:
case BGP_IPV6_NODE:
case BGP_IPV6M_NODE:
vty->node = BGP_NODE;
break;
+ case LDP_IPV4_NODE:
+ case LDP_IPV6_NODE:
+ vty->node = LDP_NODE;
+ break;
+ case LDP_IPV4_IFACE_NODE:
+ vty->node = LDP_IPV4_NODE;
+ break;
+ case LDP_IPV6_IFACE_NODE:
+ vty->node = LDP_IPV6_NODE;
+ break;
+ case LDP_PSEUDOWIRE_NODE:
+ vty->node = LDP_L2VPN_NODE;
+ break;
case KEYCHAIN_KEY_NODE:
vty->node = KEYCHAIN_NODE;
break;
+ case LINK_PARAMS_NODE:
+ vty->node = INTERFACE_NODE;
+ break;
default:
break;
}
@@ -2948,11 +3023,11 @@ DEFUN (config_end,
{
case VIEW_NODE:
case ENABLE_NODE:
- case RESTRICTED_NODE:
/* Nothing to do. */
break;
case CONFIG_NODE:
case INTERFACE_NODE:
+ case NS_NODE:
case VRF_NODE:
case ZEBRA_NODE:
case RIP_NODE:
@@ -2960,6 +3035,9 @@ DEFUN (config_end,
case BGP_NODE:
case BGP_ENCAP_NODE:
case BGP_ENCAPV6_NODE:
+ case BGP_VNC_DEFAULTS_NODE:
+ case BGP_VNC_NVE_GROUP_NODE:
+ case BGP_VNC_L2_GROUP_NODE:
case BGP_VPNV4_NODE:
case BGP_VPNV6_NODE:
case BGP_IPV4_NODE:
@@ -2969,12 +3047,20 @@ DEFUN (config_end,
case RMAP_NODE:
case OSPF_NODE:
case OSPF6_NODE:
+ case LDP_NODE:
+ case LDP_IPV4_NODE:
+ case LDP_IPV6_NODE:
+ case LDP_IPV4_IFACE_NODE:
+ case LDP_IPV6_IFACE_NODE:
+ case LDP_L2VPN_NODE:
+ case LDP_PSEUDOWIRE_NODE:
case ISIS_NODE:
case KEYCHAIN_NODE:
case KEYCHAIN_KEY_NODE:
case MASC_NODE:
case PIM_NODE:
case VTY_NODE:
+ case LINK_PARAMS_NODE:
vty_config_unlock (vty);
vty->node = ENABLE_NODE;
break;
@@ -3060,6 +3146,9 @@ DEFUN (config_write_file,
struct vty *file_vty;
struct stat conf_stat;
+ if (host.noconfig)
+ return CMD_SUCCESS;
+
/* Check and see if we are operating under vtysh configuration */
if (host.config == NULL)
{
@@ -3184,6 +3273,9 @@ DEFUN (config_write_terminal,
unsigned int i;
struct cmd_node *node;
+ if (host.noconfig)
+ return CMD_SUCCESS;
+
if (vty->type == VTY_SHELL_SERV)
{
for (i = 0; i < vector_active (cmdvec); i++)
@@ -3227,6 +3319,11 @@ DEFUN (show_startup_config,
char buf[BUFSIZ];
FILE *confp;
+ if (host.noconfig)
+ return CMD_SUCCESS;
+ if (host.config == NULL)
+ return CMD_WARNING;
+
confp = fopen (host.config, "r");
if (confp == NULL)
{
@@ -3575,6 +3672,7 @@ DEFUN (config_logmsg,
zlog(NULL, level, "%s", ((message = argv_concat(argv, argc, 1)) ? message : ""));
if (message)
XFREE(MTYPE_TMP, message);
+
return CMD_SUCCESS;
}
@@ -4094,6 +4192,12 @@ host_config_set (const char *filename)
host.config = XSTRDUP (MTYPE_HOST, filename);
}
+const char *
+host_config_get (void)
+{
+ return host.config;
+}
+
void
install_default (enum node_type node)
{
@@ -4110,10 +4214,16 @@ install_default (enum node_type node)
install_element (node, &show_running_config_cmd);
}
-/* Initialize command interface. Install basic nodes and commands. */
+/* Initialize command interface. Install basic nodes and commands.
+ *
+ * terminal = 0 -- vtysh / no logging, no config control
+ * terminal = 1 -- normal daemon
+ * terminal = -1 -- watchquagga / no logging, but minimal config control */
void
cmd_init (int terminal)
{
+ qobj_init ();
+
command_cr = XSTRDUP(MTYPE_CMD_TOKENS, "<cr>");
token_cr.type = TOKEN_TERMINAL;
token_cr.terminal = TERMINAL_LITERAL;
@@ -4129,6 +4239,7 @@ cmd_init (int terminal)
host.enable = NULL;
host.logfile = NULL;
host.config = NULL;
+ host.noconfig = (terminal < 0);
host.lines = -1;
host.motd = default_motd;
host.motdfile = NULL;
@@ -4138,7 +4249,6 @@ cmd_init (int terminal)
install_node (&enable_node, NULL);
install_node (&auth_node, NULL);
install_node (&auth_enable_node, NULL);
- install_node (&restricted_node, NULL);
install_node (&config_node, config_write_host);
/* Each node's basic commands. */
@@ -4155,43 +4265,37 @@ cmd_init (int terminal)
install_element (VIEW_NODE, &show_logging_cmd);
install_element (VIEW_NODE, &show_commandtree_cmd);
install_element (VIEW_NODE, &echo_cmd);
-
- install_element (RESTRICTED_NODE, &config_list_cmd);
- install_element (RESTRICTED_NODE, &config_exit_cmd);
- install_element (RESTRICTED_NODE, &config_quit_cmd);
- install_element (RESTRICTED_NODE, &config_help_cmd);
- install_element (RESTRICTED_NODE, &config_enable_cmd);
- install_element (RESTRICTED_NODE, &config_terminal_length_cmd);
- install_element (RESTRICTED_NODE, &config_terminal_no_length_cmd);
- install_element (RESTRICTED_NODE, &echo_cmd);
}
if (terminal)
{
- install_default (ENABLE_NODE);
+ install_element (ENABLE_NODE, &config_end_cmd);
install_element (ENABLE_NODE, &config_disable_cmd);
install_element (ENABLE_NODE, &config_terminal_cmd);
install_element (ENABLE_NODE, &copy_runningconfig_startupconfig_cmd);
+ install_element (ENABLE_NODE, &config_write_terminal_cmd);
+ install_element (ENABLE_NODE, &config_write_file_cmd);
+ install_element (ENABLE_NODE, &config_write_memory_cmd);
+ install_element (ENABLE_NODE, &config_write_cmd);
+ install_element (ENABLE_NODE, &show_running_config_cmd);
}
install_element (ENABLE_NODE, &show_startup_config_cmd);
- install_element (ENABLE_NODE, &show_version_cmd);
- install_element (ENABLE_NODE, &show_commandtree_cmd);
if (terminal)
{
- install_element (ENABLE_NODE, &config_terminal_length_cmd);
- install_element (ENABLE_NODE, &config_terminal_no_length_cmd);
- install_element (ENABLE_NODE, &show_logging_cmd);
- install_element (ENABLE_NODE, &echo_cmd);
install_element (ENABLE_NODE, &config_logmsg_cmd);
-
install_default (CONFIG_NODE);
+
+ install_element (VIEW_NODE, &show_thread_cpu_cmd);
+ install_element (ENABLE_NODE, &clear_thread_cpu_cmd);
+
+ install_element (VIEW_NODE, &show_work_queues_cmd);
}
install_element (CONFIG_NODE, &hostname_cmd);
install_element (CONFIG_NODE, &no_hostname_cmd);
- if (terminal)
+ if (terminal > 0)
{
install_element (CONFIG_NODE, &password_cmd);
install_element (CONFIG_NODE, &password_text_cmd);
@@ -4230,14 +4334,6 @@ cmd_init (int terminal)
install_element (CONFIG_NODE, &service_terminal_length_cmd);
install_element (CONFIG_NODE, &no_service_terminal_length_cmd);
- install_element (VIEW_NODE, &show_thread_cpu_cmd);
- install_element (ENABLE_NODE, &show_thread_cpu_cmd);
- install_element (RESTRICTED_NODE, &show_thread_cpu_cmd);
-
- install_element (ENABLE_NODE, &clear_thread_cpu_cmd);
- install_element (VIEW_NODE, &show_work_queues_cmd);
- install_element (ENABLE_NODE, &show_work_queues_cmd);
-
vrf_install_commands ();
}
srandom(time(NULL));
@@ -4311,6 +4407,9 @@ cmd_terminate ()
cmd_terminate_element(cmd_element);
vector_free (cmd_node_v);
+ hash_clean (cmd_node->cmd_hash, NULL);
+ hash_free (cmd_node->cmd_hash);
+ cmd_node->cmd_hash = NULL;
}
vector_free (cmdvec);