diff options
Diffstat (limited to 'lib/command.c')
-rw-r--r-- | lib/command.c | 202 |
1 files changed, 182 insertions, 20 deletions
diff --git a/lib/command.c b/lib/command.c index 8cbecce1..5d429338 100644 --- a/lib/command.c +++ b/lib/command.c @@ -24,6 +24,7 @@ Boston, MA 02111-1307, USA. */ #include "memory.h" #include "log.h" #include "version.h" +#include "thread.h" /* Command vector which includes some level of command lists. Normally each daemon maintains each own cmdvec. */ @@ -717,6 +718,8 @@ cmd_ipv6_match (char *str) int state = STATE_START; int colons = 0, nums = 0, double_colon = 0; char *sp = NULL; + struct sockaddr_in6 sin6_dummy; + int ret; if (str == NULL) return partly_match; @@ -724,6 +727,15 @@ cmd_ipv6_match (char *str) if (strspn (str, IPV6_ADDR_STR) != strlen (str)) return no_match; + /* use inet_pton that has a better support, + * for example inet_pton can support the automatic addresses: + * ::1.2.3.4 + */ + ret = inet_pton(AF_INET6, str, &sin6_dummy.sin6_addr); + + if (ret == 1) + return exact_match; + while (*str != '\0') { switch (state) @@ -1411,9 +1423,21 @@ desc_unique_string (vector v, char *str) return 0; } +int +cmd_try_do_shortcut (enum node_type node, char* first_word) { + if ( first_word != NULL && + node != AUTH_NODE && + node != VIEW_NODE && + node != AUTH_ENABLE_NODE && + node != ENABLE_NODE && + 0 == strcmp( "do", first_word ) ) + return 1; + return 0; +} + /* '?' describe command support. */ vector -cmd_describe_command (vector vline, struct vty *vty, int *status) +cmd_describe_command_real (vector vline, struct vty *vty, int *status) { int i; vector cmd_vector; @@ -1536,6 +1560,40 @@ cmd_describe_command (vector vline, struct vty *vty, int *status) return matchvec; } +vector +cmd_describe_command (vector vline, struct vty *vty, int *status) +{ + vector ret; + + if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) ) + { + enum node_type onode; + vector shifted_vline; + int index; + + onode = vty->node; + vty->node = ENABLE_NODE; + /* We can try it on enable node, cos' the vty is authenticated */ + + shifted_vline = vector_init (vector_count(vline)); + /* use memcpy? */ + for (index = 1; index < vector_max (vline); index++) + { + vector_set_index (shifted_vline, index-1, vector_lookup(vline, index)); + } + + ret = cmd_describe_command_real (shifted_vline, vty, status); + + vector_free(shifted_vline); + vty->node = onode; + return ret; + } + + + return cmd_describe_command_real (vline, vty, status); +} + + /* Check LCD of matched command. */ int cmd_lcd (char **matched) @@ -1571,7 +1629,7 @@ cmd_lcd (char **matched) /* Command line completion support. */ char ** -cmd_complete_command (vector vline, struct vty *vty, int *status) +cmd_complete_command_real (vector vline, struct vty *vty, int *status) { int i; vector cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node)); @@ -1717,9 +1775,68 @@ cmd_complete_command (vector vline, struct vty *vty, int *status) return match_str; } +char ** +cmd_complete_command (vector vline, struct vty *vty, int *status) +{ + char **ret; + + if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) ) + { + enum node_type onode; + vector shifted_vline; + int index; + + onode = vty->node; + vty->node = ENABLE_NODE; + /* We can try it on enable node, cos' the vty is authenticated */ + + shifted_vline = vector_init (vector_count(vline)); + /* use memcpy? */ + for (index = 1; index < vector_max (vline); index++) + { + vector_set_index (shifted_vline, index-1, vector_lookup(vline, index)); + } + + ret = cmd_complete_command_real (shifted_vline, vty, status); + + vector_free(shifted_vline); + vty->node = onode; + return ret; + } + + + return cmd_complete_command_real (vline, vty, status); +} + +/* return parent node */ +/* MUST eventually converge on CONFIG_NODE */ +enum node_type node_parent ( enum node_type node ) +{ + enum node_type ret; + + assert (node > CONFIG_NODE); + + switch (node) + { + case BGP_VPNV4_NODE: + case BGP_IPV4_NODE: + case BGP_IPV4M_NODE: + case BGP_IPV6_NODE: + ret = BGP_NODE; + break; + case KEYCHAIN_KEY_NODE: + ret = KEYCHAIN_NODE; + break; + default: + ret = CONFIG_NODE; + } + + return ret; +} + /* Execute command by argument vline vector. */ int -cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) +cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cmd) { int i; int index; @@ -1842,6 +1959,60 @@ cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) return (*matched_element->func) (matched_element, vty, argc, argv); } + +int +cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) { + int ret, saved_ret, tried = 0; + enum node_type onode, try_node; + + onode = try_node = vty->node; + + if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) ) + { + vector shifted_vline; + int index; + + vty->node = ENABLE_NODE; + /* We can try it on enable node, cos' the vty is authenticated */ + + shifted_vline = vector_init (vector_count(vline)); + /* use memcpy? */ + for (index = 1; index < vector_max (vline); index++) + { + vector_set_index (shifted_vline, index-1, vector_lookup(vline, index)); + } + + ret = cmd_execute_command_real (shifted_vline, vty, cmd); + + vector_free(shifted_vline); + vty->node = onode; + return ret; + } + + + saved_ret = ret = cmd_execute_command_real (vline, vty, cmd); + + /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */ + while ( ret != CMD_SUCCESS && ret != CMD_WARNING + && vty->node > CONFIG_NODE ) + { + try_node = node_parent(try_node); + vty->node = try_node; + ret = cmd_execute_command_real (vline, vty, cmd); + tried = 1; + if (ret == CMD_SUCCESS || ret == CMD_WARNING) + { + /* succesfull command, leave the node as is */ + return ret; + } + } + /* no command succeeded, reset the vty to the original node and + return the error for this node */ + if ( tried ) + vty->node = onode; + return saved_ret; +} + /* Execute command by argument readline. */ int cmd_execute_command_strict (vector vline, struct vty *vty, @@ -1981,26 +2152,12 @@ config_from_file (struct vty *vty, FILE *fp) ret = cmd_execute_command_strict (vline, vty, NULL); /* Try again with setting node to CONFIG_NODE */ - if (ret != CMD_SUCCESS && ret != CMD_WARNING) - { - if (vty->node == KEYCHAIN_KEY_NODE) - { - vty->node = KEYCHAIN_NODE; - - ret = cmd_execute_command_strict (vline, vty, NULL); - - if (ret != CMD_SUCCESS && ret != CMD_WARNING) + while (ret != CMD_SUCCESS && ret != CMD_WARNING + && vty->node != CONFIG_NODE) { - vty->node = CONFIG_NODE; + vty->node = node_parent(vty->node); ret = cmd_execute_command_strict (vline, vty, NULL); } - } - else - { - vty->node = CONFIG_NODE; - ret = cmd_execute_command_strict (vline, vty, NULL); - } - } cmd_free_strvec (vline); @@ -2977,5 +3134,10 @@ cmd_init (int terminal) install_element (CONFIG_NODE, &no_service_terminal_length_cmd); } + if (terminal) + { + install_element(VIEW_NODE, &show_thread_cpu_cmd); + install_element(ENABLE_NODE, &show_thread_cpu_cmd); + } srand(time(NULL)); } |