diff options
Diffstat (limited to 'lib/command.c')
| -rw-r--r-- | lib/command.c | 185 |
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, ©_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); |
