diff options
Diffstat (limited to 'vtysh')
-rwxr-xr-x | vtysh/extract.pl.in | 6 | ||||
-rw-r--r-- | vtysh/vtysh.c | 160 | ||||
-rw-r--r-- | vtysh/vtysh.h | 4 | ||||
-rw-r--r-- | vtysh/vtysh_config.c | 2 | ||||
-rw-r--r-- | vtysh/vtysh_main.c | 42 |
5 files changed, 203 insertions, 11 deletions
diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index ca869b64..65de23f7 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -45,7 +45,7 @@ $ignore{'"router zebra"'} = "ignore"; $ignore{'"address-family ipv4"'} = "ignore"; $ignore{'"address-family ipv4 (unicast|multicast)"'} = "ignore"; $ignore{'"address-family ipv6"'} = "ignore"; -$ignore{'"address-family ipv6 unicast"'} = "ignore"; +$ignore{'"address-family ipv6 (unicast|multicast)"'} = "ignore"; $ignore{'"address-family vpnv4"'} = "ignore"; $ignore{'"address-family vpnv4 unicast"'} = "ignore"; $ignore{'"address-family ipv4 vrf NAME"'} = "ignore"; @@ -180,7 +180,7 @@ foreach (@ARGV) { } } -my $bad_cli_stomps = 89; +my $bad_cli_stomps = 105; # Currently we have $bad_cli_stomps. This was determined by # running this script and counting up the collisions from what # was returned. @@ -220,7 +220,7 @@ foreach (keys %live) { # Output install_element print <<EOF; void -vtysh_init_cmd () +vtysh_init_cmd (void) { EOF diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 63b596a5..0d585f55 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -34,6 +34,9 @@ #include "memory.h" #include "vtysh/vtysh.h" #include "log.h" +#include "filter.h" +#include "linklist.h" +#include "prefix.h" #include "bgpd/bgp_vty.h" #include "vrf.h" @@ -423,6 +426,157 @@ vtysh_execute (const char *line) return vtysh_execute_func (line, 1); } +int +vtysh_mark_file (const char *filename) +{ + struct vty *vty; + FILE *confp = NULL; + int ret; + vector vline; + int tried = 0; + struct cmd_element *cmd; + int saved_ret, prev_node; + int lineno = 0; + + if (strncmp("-", filename, 1) == 0) + confp = stdin; + else + confp = fopen (filename, "r"); + + if (confp == NULL) + return (1); + + vty = vty_new (); + vty->fd = 0; /* stdout */ + vty->type = VTY_TERM; + vty->node = CONFIG_NODE; + + vtysh_execute_no_pager ("enable"); + vtysh_execute_no_pager ("configure terminal"); + + while (fgets (vty->buf, VTY_BUFSIZ, confp)) + { + lineno++; + tried = 0; + + if (vty->buf[0] == '!' || vty->buf[1] == '#') + { + fprintf(stdout, "%s", vty->buf); + continue; + } + + /* Split readline string up into the vector. */ + vline = cmd_make_strvec (vty->buf); + + if (vline == NULL) + { + fprintf(stdout, "%s", vty->buf); + continue; + } + + prev_node = vty->node; + saved_ret = ret = cmd_execute_command_strict (vline, vty, &cmd); + + /* If command doesn't succeeded in current node, try to walk up in node tree. + * Changing vty->node is enough to try it just out without actual walkup in + * the vtysh. */ + while (ret != CMD_SUCCESS && ret != CMD_SUCCESS_DAEMON && ret != CMD_WARNING + && vty->node > CONFIG_NODE) + { + vty->node = node_parent(vty->node); + ret = cmd_execute_command_strict (vline, vty, &cmd); + tried++; + } + + /* If command succeeded in any other node than current (tried > 0) we have + * to move into node in the vtysh where it succeeded. */ + if (ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON || ret == CMD_WARNING) + { + if ((prev_node == BGP_VPNV4_NODE || prev_node == BGP_IPV4_NODE + || prev_node == BGP_IPV6_NODE || prev_node == BGP_IPV4M_NODE + || prev_node == BGP_IPV6M_NODE) + && (tried == 1)) + { + fprintf(stdout, "exit-address-family\n"); + } + else if ((prev_node == KEYCHAIN_KEY_NODE) && (tried == 1)) + { + fprintf(stdout, "exit\n"); + } + else if (tried) + { + fprintf(stdout, "end\n"); + } + } + /* If command didn't succeed in any node, continue with return value from + * first try. */ + else if (tried) + { + ret = saved_ret; + vty->node = prev_node; + } + + cmd_free_strvec (vline); + switch (ret) + { + case CMD_WARNING: + if (vty->type == VTY_FILE) + fprintf (stderr,"line %d: Warning...: %s\n", lineno, vty->buf); + fclose(confp); + vty_close(vty); + return (1); + case CMD_ERR_AMBIGUOUS: + fprintf (stderr,"line %d: %% Ambiguous command: %s\n", lineno, vty->buf); + fclose(confp); + vty_close(vty); + return(1); + case CMD_ERR_NO_MATCH: + fprintf (stderr,"line %d: %% Unknown command: %s\n", lineno, vty->buf); + fclose(confp); + vty_close(vty); + return(1); + case CMD_ERR_INCOMPLETE: + fprintf (stderr,"line %d: %% Command incomplete: %s\n", lineno, vty->buf); + fclose(confp); + vty_close(vty); + return(1); + case CMD_SUCCESS: + fprintf(stdout, "%s", vty->buf); + break; + case CMD_SUCCESS_DAEMON: + { + u_int i; + int cmd_stat = CMD_SUCCESS; + + fprintf(stdout, "%s", vty->buf); + for (i = 0; i < array_size(vtysh_client); i++) + { + if (cmd->daemon & vtysh_client[i].flag) + { + cmd_stat = vtysh_client_execute (&vtysh_client[i], + vty->buf, stdout); + if (cmd_stat != CMD_SUCCESS) + break; + } + } + if (cmd_stat != CMD_SUCCESS) + break; + + if (cmd->func) + (*cmd->func) (cmd, vty, 0, NULL); + } + } + } + /* This is the end */ + fprintf(stdout, "end\n"); + vty_close(vty); + + if (confp != stdin) + fclose(confp); + + return (0); +} + /* Configration make from file. */ int vtysh_config_from_file (struct vty *vty, FILE *fp) @@ -441,13 +595,13 @@ vtysh_config_from_file (struct vty *vty, FILE *fp) fprintf (stdout,"Warning...\n"); break; case CMD_ERR_AMBIGUOUS: - fprintf (stdout,"%% Ambiguous command.\n"); + fprintf (stdout,"%% Ambiguous command: %s\n", vty->buf); break; case CMD_ERR_NO_MATCH: fprintf (stdout,"%% Unknown command: %s", vty->buf); break; case CMD_ERR_INCOMPLETE: - fprintf (stdout,"%% Command incomplete.\n"); + fprintf (stdout,"%% Command incomplete: %s\n", vty->buf); break; case CMD_SUCCESS_DAEMON: { @@ -1897,6 +2051,7 @@ write_config_integrated(void) for (i = 0; i < array_size(vtysh_client); i++) vtysh_client_execute (&vtysh_client[i], line, NULL); + vtysh_config_write (); vtysh_config_dump (fp); fclose (fp); @@ -2500,6 +2655,7 @@ vtysh_init_vty (void) #ifdef HAVE_IPV6 install_element (BGP_NODE, &address_family_ipv6_cmd); install_element (BGP_NODE, &address_family_ipv6_unicast_cmd); + install_element (BGP_NODE, &address_family_ipv6_multicast_cmd); #endif install_element (BGP_VPNV4_NODE, &exit_address_family_cmd); install_element (BGP_VPNV6_NODE, &exit_address_family_cmd); diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index 1681a71a..9f8fb238 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -53,7 +53,9 @@ void vtysh_config_write (void); int vtysh_config_from_file (struct vty *, FILE *); -int vtysh_read_config (char *); +int vtysh_mark_file(const char *filename); + +int vtysh_read_config (const char *); void vtysh_config_parse (char *); diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index a069164b..4c972460 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -397,7 +397,7 @@ vtysh_read_file (FILE *confp) /* Read up configuration file from config_default_dir. */ int -vtysh_read_config (char *config_default_dir) +vtysh_read_config (const char *config_default_dir) { FILE *confp = NULL; diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index 02a19b7c..8ed69e05 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -135,8 +135,10 @@ usage (int status) "-b, --boot Execute boot startup configuration\n" \ "-c, --command Execute argument as command\n" \ "-d, --daemon Connect only to the specified daemon\n" \ + "-f, --inputfile Execute commands from specific file and exit\n" \ "-E, --echo Echo prompt and command in -c mode\n" \ "-C, --dryrun Check configuration for validity and exit\n" \ + "-m, --markfile Mark input file with context end\n" "-h, --help Display this help and exit\n\n" \ "Note that multiple commands may be executed from the command\n" \ "line by passing multiple -c args, or by embedding linefeed\n" \ @@ -154,10 +156,12 @@ struct option longopts[] = { "eval", required_argument, NULL, 'e'}, { "command", required_argument, NULL, 'c'}, { "daemon", required_argument, NULL, 'd'}, + { "inputfile", required_argument, NULL, 'f'}, { "echo", no_argument, NULL, 'E'}, { "dryrun", no_argument, NULL, 'C'}, { "help", no_argument, NULL, 'h'}, { "noerror", no_argument, NULL, 'n'}, + { "mark", no_argument, NULL, 'm'}, { 0 } }; @@ -216,6 +220,7 @@ main (int argc, char **argv, char **env) int dryrun = 0; int boot_flag = 0; const char *daemon_name = NULL; + const char *inputfile = NULL; struct cmd_rec { const char *line; struct cmd_rec *next; @@ -224,6 +229,7 @@ main (int argc, char **argv, char **env) int echo_command = 0; int no_error = 0; char *homedir = NULL; + int markfile = 0; /* Preserve name of myself. */ progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]); @@ -235,7 +241,7 @@ main (int argc, char **argv, char **env) /* Option handling. */ while (1) { - opt = getopt_long (argc, argv, "be:c:d:nEhC", longopts, 0); + opt = getopt_long (argc, argv, "be:c:d:nf:mEhC", longopts, 0); if (opt == EOF) break; @@ -264,6 +270,12 @@ main (int argc, char **argv, char **env) case 'd': daemon_name = optarg; break; + case 'f': + inputfile = optarg; + break; + case 'm': + markfile = 1; + break; case 'n': no_error = 1; break; @@ -298,12 +310,28 @@ main (int argc, char **argv, char **env) vty_init_vtysh (); /* Read vtysh configuration file before connecting to daemons. */ - vtysh_read_config (config_default); + vtysh_read_config(config_default); + + if (markfile) + { + if (!inputfile) + { + fprintf(stderr, "-f option MUST be specified with -m option\n"); + return(1); + } + return(vtysh_mark_file(inputfile)); + } /* Start execution only if not in dry-run mode */ if(dryrun) - return(0); - + { + if (inputfile) + { + vtysh_read_config(inputfile); + } + return(0); + } + /* Ignore error messages */ if (no_error) freopen("/dev/null", "w", stdout); @@ -339,6 +367,12 @@ main (int argc, char **argv, char **env) } } + if (inputfile) + { + vtysh_read_config(inputfile); + exit(0); + } + /* If eval mode. */ if (cmd) { |