* lib/command.[ch]: Make node_parent() function nonstatic. vtyh.c will
          use it as well.
        * vtysh/vtysh.c: Implement walkup in node tree for vtysh as it already
          works in vty.
diff --git a/lib/ChangeLog b/lib/ChangeLog
index d17d7e0..e3b7d37 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,8 @@
+2005-01-23 Hasso Tepper <hasso at quagga.net>
+
+	* lib/command.[ch]: Make node_parent() function nonstatic. vtyh.c will
+	  use it as well.
+
 2005-01-18 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
 
 	* log.h: Test for SA_SIGINFO to see whether zlog_signal takes final
diff --git a/lib/command.c b/lib/command.c
index 8f9b98e..6b65a5d 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -1,5 +1,5 @@
 /*
-   $Id: command.c,v 1.34 2005/01/16 23:31:54 hasso Exp $
+   $Id: command.c,v 1.35 2005/01/23 21:42:25 hasso Exp $
 
    Command interpreter routine for virtual terminal [aka TeletYpe]
    Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
@@ -1941,7 +1941,7 @@
 
 /* return parent node */
 /* MUST eventually converge on CONFIG_NODE */
-static enum node_type
+enum node_type
 node_parent ( enum node_type node )
 {
   enum node_type ret;
diff --git a/lib/command.h b/lib/command.h
index cb76896..8fdec98 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -329,6 +329,7 @@
 char **cmd_complete_command ();
 const char *cmd_prompt (enum node_type);
 int config_from_file (struct vty *, FILE *);
+enum node_type node_parent (enum node_type);
 int cmd_execute_command (vector, struct vty *, struct cmd_element **, int);
 int cmd_execute_command_strict (vector, struct vty *, struct cmd_element **);
 void config_replace_string (struct cmd_element *, char *, ...);
diff --git a/vtysh/ChangeLog b/vtysh/ChangeLog
index 1cc1fb8..e142f15 100644
--- a/vtysh/ChangeLog
+++ b/vtysh/ChangeLog
@@ -2,6 +2,8 @@
 
 	* vtysh.conf.sample: Fix typo "integrated-vtysh-conf" ->
 	  "integrated-vtysh-config".
+	* vtysh/vtysh.c: Implement walkup in node tree for vtysh as it
+	  already works in vty.
 
 2005-01-10 Hasso Tepper <hasso at quagga.net>
 
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 6ece45f..a9929c5 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -254,7 +254,9 @@
   vector vline;
   struct cmd_element *cmd;
   FILE *fp = NULL;
-  int closepager=0;
+  int closepager = 0;
+  int tried = 0;
+  int saved_ret, saved_node;
 
   /* Split readline string up into the vector. */
   vline = cmd_make_strvec (line);
@@ -262,7 +264,48 @@
   if (vline == NULL)
     return;
 
-  ret = cmd_execute_command (vline, vty, &cmd, 1);
+  saved_ret = ret = cmd_execute_command (vline, vty, &cmd, 1);
+  saved_node = vty->node;
+
+  /* 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 (vline, vty, &cmd, 1);
+      tried++;
+    }
+
+  vty->node = saved_node;
+
+  /* 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 ((saved_node == BGP_VPNV4_NODE || saved_node == BGP_IPV4_NODE
+	   || saved_node == BGP_IPV6_NODE || saved_node == BGP_IPV4M_NODE)
+	  && (tried == 1))
+	{
+	  vtysh_execute("exit-address-family");
+	}
+      else if ((saved_node == KEYCHAIN_KEY_NODE) && (tried == 1))
+	{
+	  vtysh_execute("exit");
+	}
+      else if (tried)
+	{
+	  vtysh_execute ("end");
+	  vtysh_execute ("configure terminal");
+	}
+    }
+  /* If command didn't succeed in any node, continue with return value from
+   * first try. */
+  else if (tried)
+    {
+      ret = saved_ret;
+    }
 
   cmd_free_strvec (vline);