summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2015-09-28 22:17:36 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2015-09-28 22:17:36 +0200
commitbed578b8b98978d12a6319300bb6eb3a8b4d1b63 (patch)
treee9a58202b35cba83ec812adb14906650ef9e6257
parentBGP: Fix source route type in redistributed route (diff)
downloadfrr-bed578b8b98978d12a6319300bb6eb3a8b4d1b63.tar.xz
frr-bed578b8b98978d12a6319300bb6eb3a8b4d1b63.zip
vtysh: Fix Quagga.conf file read in.
There exists a sequence of cli commands that are successfully read in by bgpd.conf, but not by a consolidated Quagga.conf. This issue stems from the fact that the consolidated config file attempts to match the current node + 1 node up the tree, while the individual config file searches for matches all the way up the tree. Quagga.conf read-in relies on vtysh_cmd.c command parsing which puts all nodes at CONFIG_NODE and if a match is found CMD_SUCCESS_DAEMON is returned. This signals to the parser to call the appropriate daemon with the comamnd. bgp as an example has three levels of config node's. If you are reading in a config node at the 3rd level(say address-family ipv6) then transition to another node under bgp it will not work in Quagga.conf because the code only looked up one node and was at CONFIG_BGP when it failed to find a match. Ticket: CM-7625 Reviewed by: CCR-3591 Testing: See Bug Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com> Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
-rw-r--r--lib/command.c96
-rw-r--r--lib/command.h1
-rw-r--r--vtysh/vtysh.c50
3 files changed, 64 insertions, 83 deletions
diff --git a/lib/command.c b/lib/command.c
index ff3778bd7..f6cb9dc8f 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -2775,54 +2775,82 @@ cmd_execute_command_strict (vector vline, struct vty *vty,
return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd);
}
+/**
+ * Parse one line of config, walking up the parse tree attempting to find a match
+ *
+ * @param vty The vty context in which the command should be executed.
+ * @param cmd Pointer where the struct cmd_element* of the match command
+ * will be stored, if any. May be set to NULL if this info is
+ * not needed.
+ * @param use_daemon Boolean to control whether or not we match on CMD_SUCCESS_DAEMON
+ * or not.
+ * @return The status of the command that has been executed or an error code
+ * as to why no command could be executed.
+ */
+int
+command_config_read_one_line (struct vty *vty, struct cmd_element **cmd, int use_daemon)
+{
+ vector vline;
+ int saved_node;
+ int ret;
+
+ vline = cmd_make_strvec (vty->buf);
+
+ /* In case of comment line */
+ if (vline == NULL)
+ return CMD_SUCCESS;
+
+ /* Execute configuration command : this is strict match */
+ ret = cmd_execute_command_strict (vline, vty, cmd);
+
+ // Climb the tree and try the command again at each node
+ if (!(use_daemon && ret == CMD_SUCCESS_DAEMON) &&
+ ret != CMD_SUCCESS && ret != CMD_WARNING &&
+ ret != CMD_ERR_NOTHING_TODO && vty->node != CONFIG_NODE) {
+
+ saved_node = vty->node;
+
+ while (!(use_daemon && ret == CMD_SUCCESS_DAEMON) &&
+ ret != CMD_SUCCESS && ret != CMD_WARNING &&
+ ret != CMD_ERR_NOTHING_TODO && vty->node != CONFIG_NODE) {
+ vty->node = node_parent(vty->node);
+ ret = cmd_execute_command_strict (vline, vty, NULL);
+ }
+
+ // If climbing the tree did not work then ignore the command and
+ // stay at the same node
+ if (!(use_daemon && ret == CMD_SUCCESS_DAEMON) &&
+ ret != CMD_SUCCESS && ret != CMD_WARNING &&
+ ret != CMD_ERR_NOTHING_TODO)
+ {
+ vty->node = saved_node;
+
+ memcpy(vty->error_buf, vty->buf, VTY_BUFSIZ);
+ }
+ }
+
+ cmd_free_strvec (vline);
+
+ return ret;
+}
+
/* Configuration make from file. */
int
config_from_file (struct vty *vty, FILE *fp, unsigned int *line_num)
{
int ret, error_ret=0;
- int saved_node;
*line_num = 0;
- vector vline;
while (fgets (vty->buf, VTY_BUFSIZ, fp))
{
if (!error_ret)
++(*line_num);
- vline = cmd_make_strvec (vty->buf);
+ ret = command_config_read_one_line (vty, NULL, 0);
- /* In case of comment line */
- if (vline == NULL)
- continue;
- /* Execute configuration command : this is strict match */
- ret = cmd_execute_command_strict (vline, vty, NULL);
-
- // Climb the tree and try the command again at each node
if (ret != CMD_SUCCESS && ret != CMD_WARNING &&
- ret != CMD_ERR_NOTHING_TODO && vty->node != CONFIG_NODE) {
-
- saved_node = vty->node;
-
- while (ret != CMD_SUCCESS && ret != CMD_WARNING &&
- ret != CMD_ERR_NOTHING_TODO && vty->node != CONFIG_NODE) {
- vty->node = node_parent(vty->node);
- ret = cmd_execute_command_strict (vline, vty, NULL);
- }
-
- // If climbing the tree did not work then ignore the command and
- // stay at the same node
- if (ret != CMD_SUCCESS && ret != CMD_WARNING &&
- ret != CMD_ERR_NOTHING_TODO) {
- vty->node = saved_node;
-
- if (!error_ret) {
- memcpy(vty->error_buf, vty->buf, VTY_BUFSIZ);
- error_ret = ret;
- }
- }
- }
-
- cmd_free_strvec (vline);
+ ret != CMD_ERR_NOTHING_TODO)
+ error_ret = ret;
}
if (error_ret) {
diff --git a/lib/command.h b/lib/command.h
index e9bfa94e8..4eb31a694 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -532,6 +532,7 @@ extern void cmd_free_strvec (vector);
extern vector cmd_describe_command (vector, struct vty *, int *status);
extern char **cmd_complete_command (vector, struct vty *, int *status);
extern const char *cmd_prompt (enum node_type);
+extern int command_config_read_one_line (struct vty *vty, struct cmd_element **, int use_config_node);
extern int config_from_file (struct vty *, FILE *, unsigned int *line_num);
extern enum node_type node_parent (enum node_type);
extern int cmd_execute_command (vector, struct vty *, struct cmd_element **, int);
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 699a15b11..6d5f3c9e9 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -666,62 +666,14 @@ void
vtysh_config_from_file (struct vty *vty, FILE *fp)
{
int ret;
- vector vline;
struct cmd_element *cmd;
- int save_node = CONFIG_NODE;
int lineno = 0;
while (fgets (vty->buf, VTY_BUFSIZ, fp))
{
lineno++;
- if (vty->buf[0] == '!' || vty->buf[1] == '#')
- continue;
-
- vline = cmd_make_strvec (vty->buf);
- /* In case of comment line. */
- if (vline == NULL)
- continue;
-
- /* Execute configuration command : this is strict match. */
- ret = cmd_execute_command_strict (vline, vty, &cmd);
-
- /* Try again with setting node to CONFIG_NODE. */
- if (ret != CMD_SUCCESS
- && ret != CMD_SUCCESS_DAEMON
- && ret != CMD_WARNING)
- {
- if (vty->node == KEYCHAIN_KEY_NODE)
- {
- vty->node = KEYCHAIN_NODE;
- vtysh_exit_ripd_only ();
- ret = cmd_execute_command_strict (vline, vty, &cmd);
-
- if (ret != CMD_SUCCESS
- && ret != CMD_SUCCESS_DAEMON
- && ret != CMD_WARNING)
- {
- vtysh_exit_ripd_only ();
- vty->node = CONFIG_NODE;
- ret = cmd_execute_command_strict (vline, vty, &cmd);
- }
- }
- else
- {
- save_node = vty->node;
- vty->node = CONFIG_NODE;
- ret = cmd_execute_command_strict (vline, vty, &cmd);
-
- // If the command did not work at CONFIG_NODE either then ignore
- // the command and go back to our previous node.
- if ((ret != CMD_SUCCESS) &&
- (ret != CMD_SUCCESS_DAEMON) &&
- (ret != CMD_WARNING))
- vty->node = save_node;
- }
- }
-
- cmd_free_strvec (vline);
+ ret = command_config_read_one_line (vty, &cmd, 1);
switch (ret)
{