]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/zebra_vty.c
*: nuke ^L (page feed)
[mirror_frr.git] / zebra / zebra_vty.c
index 9830e5b1e1dfba1a0329f946fef420ecb3100325..baa60db9a71f083dd276aa216266bb23b8e2998a 100644 (file)
 
 #include <zebra.h>
 
+#include "memory.h"
 #include "if.h"
 #include "prefix.h"
 #include "command.h"
 #include "table.h"
 #include "rib.h"
 
-/* Return route type string for VTY output.  */
-const char *
-route_type_str (u_char type)
-{
-  switch (type)
-    {
-    case ZEBRA_ROUTE_SYSTEM:
-      return "system";
-    case ZEBRA_ROUTE_KERNEL:
-      return "kernel";
-    case ZEBRA_ROUTE_CONNECT:
-      return "connected";
-    case ZEBRA_ROUTE_STATIC:
-      return "static";
-    case ZEBRA_ROUTE_RIP:
-      return "rip";
-    case ZEBRA_ROUTE_RIPNG:
-      return "rip";
-    case ZEBRA_ROUTE_OSPF:
-      return "ospf";
-    case ZEBRA_ROUTE_OSPF6:
-      return "ospf";
-    case ZEBRA_ROUTE_ISIS:
-      return "isis";
-    case ZEBRA_ROUTE_BGP:
-      return "bgp";
-    default:
-      return "unknown";
-    }
-};
+#include "zebra/zserv.h"
 
-/* Return route type string for VTY output.  */
-char
-route_type_char (u_char type)
-{
-  switch (type)
-    {
-    case ZEBRA_ROUTE_SYSTEM:
-      return 'S';
-    case ZEBRA_ROUTE_KERNEL:
-      return 'K';
-    case ZEBRA_ROUTE_CONNECT:
-      return 'C';
-    case ZEBRA_ROUTE_STATIC:
-      return 'S';
-    case ZEBRA_ROUTE_RIP:
-      return 'R';
-    case ZEBRA_ROUTE_RIPNG:
-      return 'R';
-    case ZEBRA_ROUTE_OSPF:
-      return 'O';
-    case ZEBRA_ROUTE_OSPF6:
-      return 'O';
-    case ZEBRA_ROUTE_ISIS:
-      return 'I';
-    case ZEBRA_ROUTE_BGP:
-      return 'B';
-    default:
-      return '?';
-    }
-};
-\f
 /* General fucntion for static route. */
-int
+static int
 zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str,
                   const char *mask_str, const char *gate_str,
                   const char *flag_str, const char *distance_str)
@@ -339,9 +280,9 @@ DEFUN (ip_route_mask_flags_distance,
        "IP destination prefix mask\n"
        "IP gateway address\n"
        "IP gateway interface name\n"
-       "Distance value for this route\n"
        "Emit an ICMP unreachable when matched\n"
-       "Silently discard pkts when matched\n")
+       "Silently discard pkts when matched\n"
+       "Distance value for this route\n")
 {
   return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4]);
 }
@@ -353,9 +294,9 @@ DEFUN (ip_route_mask_flags_distance2,
        "Establish static routes\n"
        "IP destination prefix\n"
        "IP destination prefix mask\n"
-       "Distance value for this route\n"
        "Emit an ICMP unreachable when matched\n"
-       "Silently discard pkts when matched\n")
+       "Silently discard pkts when matched\n"
+       "Distance value for this route\n")
 {
   return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3]);
 }
@@ -534,20 +475,74 @@ DEFUN (no_ip_route_mask_flags_distance2,
   return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3]);
 }
 
+char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];    /* "any" == ZEBRA_ROUTE_MAX */
+
+DEFUN (ip_protocol,
+       ip_protocol_cmd,
+       "ip protocol PROTO route-map ROUTE-MAP",
+       NO_STR
+       "Apply route map to PROTO\n"
+       "Protocol name\n"
+       "Route map name\n")
+{
+  int i;
+
+  if (strcasecmp(argv[0], "any") == 0)
+    i = ZEBRA_ROUTE_MAX;
+  else
+    i = proto_name2num(argv[0]);
+  if (i < 0)
+    {
+      vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  if (proto_rm[AFI_IP][i])
+    XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]);
+  proto_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_protocol,
+       no_ip_protocol_cmd,
+       "no ip protocol PROTO",
+       NO_STR
+       "Remove route map from PROTO\n"
+       "Protocol name\n")
+{
+  int i;
+
+  if (strcasecmp(argv[0], "any") == 0)
+    i = ZEBRA_ROUTE_MAX;
+  else
+    i = proto_name2num(argv[0]);
+  if (i < 0)
+    {
+      vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
+               VTY_NEWLINE);
+     return CMD_WARNING;
+    }
+  if (proto_rm[AFI_IP][i])
+    XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]);
+  proto_rm[AFI_IP][i] = NULL;
+  return CMD_SUCCESS;
+}
+
 /* New RIB.  Detailed information for IPv4 route. */
-void
+static void
 vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
 {
   struct rib *rib;
-  struct nexthop *nexthop;
+  struct nexthop *nexthop, *tnexthop;
+  int recursing;
 
-  for (rib = rn->info; rib; rib = rib->next)
+  RNODE_FOREACH_RIB (rn, rib)
     {
       vty_out (vty, "Routing entry for %s/%d%s", 
               inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
               VTY_NEWLINE);
-      vty_out (vty, "  Known via \"%s\"", route_type_str (rib->type));
-      vty_out (vty, ", distance %d, metric %d", rib->distance, rib->metric);
+      vty_out (vty, "  Known via \"%s\"", zebra_route_string (rib->type));
+      vty_out (vty, ", distance %u, metric %u", rib->distance, rib->metric);
       if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
        vty_out (vty, ", best");
       if (rib->refcnt)
@@ -562,6 +557,7 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
 #define ONE_WEEK_SECOND 60*60*24*7
       if (rib->type == ZEBRA_ROUTE_RIP
          || rib->type == ZEBRA_ROUTE_OSPF
+         || rib->type == ZEBRA_ROUTE_BABEL
          || rib->type == ZEBRA_ROUTE_ISIS
          || rib->type == ZEBRA_ROUTE_BGP)
        {
@@ -587,10 +583,13 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
          vty_out (vty, " ago%s", VTY_NEWLINE);
        }
 
-      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+      for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
        {
-         vty_out (vty, "  %c",
-                  CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
+          char addrstr[32];
+
+         vty_out (vty, "  %c%s",
+                  CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ',
+                  recursing ? "  " : "");
 
          switch (nexthop->type)
            {
@@ -616,46 +615,61 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
          if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
            vty_out (vty, " inactive");
 
+         if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
+           vty_out (vty, " onlink");
+
          if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
-           {
-             vty_out (vty, " (recursive");
-               
-             switch (nexthop->rtype)
-               {
-               case NEXTHOP_TYPE_IPV4:
-               case NEXTHOP_TYPE_IPV4_IFINDEX:
-                 vty_out (vty, " via %s)", inet_ntoa (nexthop->rgate.ipv4));
-                 break;
-               case NEXTHOP_TYPE_IFINDEX:
-               case NEXTHOP_TYPE_IFNAME:
-                 vty_out (vty, " is directly connected, %s)",
-                          ifindex2ifname (nexthop->rifindex));
-                 break;
-               default:
-                 break;
-               }
-           }
+           vty_out (vty, " (recursive)");
+
+         switch (nexthop->type)
+            {
+            case NEXTHOP_TYPE_IPV4:
+            case NEXTHOP_TYPE_IPV4_IFINDEX:
+            case NEXTHOP_TYPE_IPV4_IFNAME:
+              if (nexthop->src.ipv4.s_addr)
+                {
+                 if (inet_ntop(AF_INET, &nexthop->src.ipv4, addrstr,
+                     sizeof addrstr))
+                    vty_out (vty, ", src %s", addrstr);
+                }
+              break;
+#ifdef HAVE_IPV6
+            case NEXTHOP_TYPE_IPV6:
+            case NEXTHOP_TYPE_IPV6_IFINDEX:
+            case NEXTHOP_TYPE_IPV6_IFNAME:
+              if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
+                {
+                 if (inet_ntop(AF_INET6, &nexthop->src.ipv6, addrstr,
+                     sizeof addrstr))
+                    vty_out (vty, ", src %s", addrstr);
+                }
+              break;
+#endif /* HAVE_IPV6 */
+            default:
+              break;
+            }
          vty_out (vty, "%s", VTY_NEWLINE);
        }
       vty_out (vty, "%s", VTY_NEWLINE);
     }
 }
 
-void
+static void
 vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
 {
-  struct nexthop *nexthop;
+  struct nexthop *nexthop, *tnexthop;
+  int recursing;
   int len = 0;
   char buf[BUFSIZ];
 
   /* Nexthop information. */
-  for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+  for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
     {
       if (nexthop == rib->nexthop)
        {
          /* Prefix information. */
          len = vty_out (vty, "%c%c%c %s/%d",
-                        route_type_char (rib->type),
+                        zebra_route_char (rib->type),
                         CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)
                         ? '>' : ' ',
                         CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
@@ -673,7 +687,7 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
        vty_out (vty, "  %c%*c",
                 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
                 ? '*' : ' ',
-                len - 3, ' ');
+                len - 3 + (2 * recursing), ' ');
 
       switch (nexthop->type)
        {
@@ -699,25 +713,37 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
       if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
        vty_out (vty, " inactive");
 
+      if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
+       vty_out (vty, " onlink");
+
       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
-       {
-         vty_out (vty, " (recursive");
-               
-         switch (nexthop->rtype)
-           {
-           case NEXTHOP_TYPE_IPV4:
-           case NEXTHOP_TYPE_IPV4_IFINDEX:
-             vty_out (vty, " via %s)", inet_ntoa (nexthop->rgate.ipv4));
-             break;
-           case NEXTHOP_TYPE_IFINDEX:
-           case NEXTHOP_TYPE_IFNAME:
-             vty_out (vty, " is directly connected, %s)",
-                      ifindex2ifname (nexthop->rifindex));
-             break;
-           default:
-             break;
-           }
-       }
+       vty_out (vty, " (recursive)");
+
+      switch (nexthop->type)
+        {
+          case NEXTHOP_TYPE_IPV4:
+          case NEXTHOP_TYPE_IPV4_IFINDEX:
+          case NEXTHOP_TYPE_IPV4_IFNAME:
+            if (nexthop->src.ipv4.s_addr)
+              {
+               if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, sizeof buf))
+                  vty_out (vty, ", src %s", buf);
+              }
+            break;
+#ifdef HAVE_IPV6
+          case NEXTHOP_TYPE_IPV6:
+          case NEXTHOP_TYPE_IPV6_IFINDEX:
+          case NEXTHOP_TYPE_IPV6_IFNAME:
+            if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
+              {
+               if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, sizeof buf))
+                  vty_out (vty, ", src %s", buf);
+              }
+            break;
+#endif /* HAVE_IPV6 */
+          default:
+           break;
+        }
 
       if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
                vty_out (vty, ", bh");
@@ -726,6 +752,7 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
 
       if (rib->type == ZEBRA_ROUTE_RIP
          || rib->type == ZEBRA_ROUTE_OSPF
+         || rib->type == ZEBRA_ROUTE_BABEL
          || rib->type == ZEBRA_ROUTE_ISIS
          || rib->type == ZEBRA_ROUTE_BGP)
        {
@@ -754,10 +781,6 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
     }
 }
 
-#define SHOW_ROUTE_V4_HEADER "Codes: K - kernel route, C - connected, " \
-  "S - static, R - RIP, O - OSPF,%s       I - ISIS, B - BGP, " \
-  "> - selected route, * - FIB route%s%s"
-
 DEFUN (show_ip_route,
        show_ip_route_cmd,
        "show ip route",
@@ -776,12 +799,11 @@ DEFUN (show_ip_route,
 
   /* Show all IPv4 routes. */
   for (rn = route_top (table); rn; rn = route_next (rn))
-    for (rib = rn->info; rib; rib = rib->next)
+    RNODE_FOREACH_RIB (rn, rib)
       {
        if (first)
          {
-           vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE,
-                    VTY_NEWLINE);
+           vty_out (vty, SHOW_ROUTE_V4_HEADER);
            first = 0;
          }
        vty_show_ip_route (vty, rn, rib);
@@ -818,13 +840,12 @@ DEFUN (show_ip_route_prefix_longer,
 
   /* Show matched type IPv4 routes. */
   for (rn = route_top (table); rn; rn = route_next (rn))
-    for (rib = rn->info; rib; rib = rib->next)
+    RNODE_FOREACH_RIB (rn, rib)
       if (prefix_match (&p, &rn->p))
        {
          if (first)
            {
-             vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE,
-                      VTY_NEWLINE, VTY_NEWLINE);
+             vty_out (vty, SHOW_ROUTE_V4_HEADER);
              first = 0;
            }
          vty_show_ip_route (vty, rn, rib);
@@ -852,7 +873,7 @@ DEFUN (show_ip_route_supernets,
 
   /* Show matched type IPv4 routes. */
   for (rn = route_top (table); rn; rn = route_next (rn))
-    for (rib = rn->info; rib; rib = rib->next)
+    RNODE_FOREACH_RIB (rn, rib)
       {
        addr = ntohl (rn->p.u.prefix4.s_addr);
 
@@ -862,8 +883,7 @@ DEFUN (show_ip_route_supernets,
          {
            if (first)
              {
-               vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE,
-                        VTY_NEWLINE, VTY_NEWLINE);
+               vty_out (vty, SHOW_ROUTE_V4_HEADER);
                first = 0;
              }
            vty_show_ip_route (vty, rn, rib);
@@ -874,17 +894,11 @@ DEFUN (show_ip_route_supernets,
 
 DEFUN (show_ip_route_protocol,
        show_ip_route_protocol_cmd,
-       "show ip route (bgp|connected|isis|kernel|ospf|rip|static)",
+       "show ip route " QUAGGA_IP_REDIST_STR_ZEBRA,
        SHOW_STR
        IP_STR
        "IP routing table\n"
-       "Border Gateway Protocol (BGP)\n"
-       "Connected\n"
-       "ISO IS-IS (ISIS)\n"
-       "Kernel\n"
-       "Open Shortest Path First (OSPF)\n"
-       "Routing Information Protocol (RIP)\n"
-       "Static routes\n")
+       QUAGGA_IP_REDIST_HELP_STR_ZEBRA)
 {
   int type;
   struct route_table *table;
@@ -892,21 +906,8 @@ DEFUN (show_ip_route_protocol,
   struct rib *rib;
   int first = 1;
 
-  if (strncmp (argv[0], "b", 1) == 0)
-    type = ZEBRA_ROUTE_BGP;
-  else if (strncmp (argv[0], "c", 1) == 0)
-    type = ZEBRA_ROUTE_CONNECT;
-  else if (strncmp (argv[0], "k", 1) ==0)
-    type = ZEBRA_ROUTE_KERNEL;
-  else if (strncmp (argv[0], "o", 1) == 0)
-    type = ZEBRA_ROUTE_OSPF;
-  else if (strncmp (argv[0], "i", 1) == 0)
-    type = ZEBRA_ROUTE_ISIS;
-  else if (strncmp (argv[0], "r", 1) == 0)
-    type = ZEBRA_ROUTE_RIP;
-  else if (strncmp (argv[0], "s", 1) == 0)
-    type = ZEBRA_ROUTE_STATIC;
-  else 
+  type = proto_redistnum (AFI_IP, argv[0]);
+  if (type < 0)
     {
       vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
       return CMD_WARNING;
@@ -918,13 +919,12 @@ DEFUN (show_ip_route_protocol,
 
   /* Show matched type IPv4 routes. */
   for (rn = route_top (table); rn; rn = route_next (rn))
-    for (rib = rn->info; rib; rib = rib->next)
+    RNODE_FOREACH_RIB (rn, rib)
       if (rib->type == type)
        {
          if (first)
            {
-             vty_out (vty, SHOW_ROUTE_V4_HEADER,
-                      VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+             vty_out (vty, SHOW_ROUTE_V4_HEADER);
              first = 0;
            }
          vty_show_ip_route (vty, rn, rib);
@@ -1008,30 +1008,68 @@ DEFUN (show_ip_route_prefix,
   return CMD_SUCCESS;
 }
 
-void
-zebra_show_ip_route (struct vty *vty, struct vrf *vrf)
+static void
+vty_show_ip_route_summary (struct vty *vty, struct route_table *table)
 {
-  vty_out (vty, "IP routing table name is %s(%d)%s",
-          vrf->name ? vrf->name : "", vrf->id, VTY_NEWLINE);
-
-  vty_out (vty, "Route Source    Networks%s", VTY_NEWLINE);
-  vty_out (vty, "connected       %d%s", 0, VTY_NEWLINE);
-  vty_out (vty, "static          %d%s", 0, VTY_NEWLINE);
-  vty_out (vty, "rip             %d%s", 0, VTY_NEWLINE);
+  struct route_node *rn;
+  struct rib *rib;
+  struct nexthop *nexthop;
+#define ZEBRA_ROUTE_IBGP  ZEBRA_ROUTE_MAX
+#define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
+  u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
+  u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
+  u_int32_t i;
+
+  memset (&rib_cnt, 0, sizeof(rib_cnt));
+  memset (&fib_cnt, 0, sizeof(fib_cnt));
+  for (rn = route_top (table); rn; rn = route_next (rn))
+    RNODE_FOREACH_RIB (rn, rib)
+      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+        {
+         rib_cnt[ZEBRA_ROUTE_TOTAL]++;
+         rib_cnt[rib->type]++;
+         if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
+             || nexthop_has_fib_child(nexthop))
+           {
+             fib_cnt[ZEBRA_ROUTE_TOTAL]++;
+             fib_cnt[rib->type]++;
+           }
+         if (rib->type == ZEBRA_ROUTE_BGP && 
+             CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP)) 
+           {
+             rib_cnt[ZEBRA_ROUTE_IBGP]++;
+             if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
+                 || nexthop_has_fib_child(nexthop))
+               fib_cnt[ZEBRA_ROUTE_IBGP]++;
+           }
+       }
 
-  vty_out (vty, "bgp             %d%s", 0, VTY_NEWLINE);
-  vty_out (vty, " External: %d Internal: %d Local: %d%s",
-          0, 0, 0, VTY_NEWLINE);
+  vty_out (vty, "%-20s %-20s %-20s %s", 
+          "Route Source", "Routes", "FIB", VTY_NEWLINE);
 
-  vty_out (vty, "ospf            %d%s", 0, VTY_NEWLINE);
-  vty_out (vty,
-          "  Intra-area: %d Inter-area: %d External-1: %d External-2: %d%s",
-          0, 0, 0, 0, VTY_NEWLINE);
-  vty_out (vty, "  NSSA External-1: %d NSSA External-2: %d%s",
-          0, 0, VTY_NEWLINE);
+  for (i = 0; i < ZEBRA_ROUTE_MAX; i++) 
+    {
+      if (rib_cnt[i] > 0)
+       {
+         if (i == ZEBRA_ROUTE_BGP)
+           {
+             vty_out (vty, "%-20s %-20d %-20d %s", "ebgp", 
+                      rib_cnt[ZEBRA_ROUTE_BGP] - rib_cnt[ZEBRA_ROUTE_IBGP],
+                      fib_cnt[ZEBRA_ROUTE_BGP] - fib_cnt[ZEBRA_ROUTE_IBGP],
+                      VTY_NEWLINE);
+             vty_out (vty, "%-20s %-20d %-20d %s", "ibgp", 
+                      rib_cnt[ZEBRA_ROUTE_IBGP], fib_cnt[ZEBRA_ROUTE_IBGP],
+                      VTY_NEWLINE);
+           }
+         else 
+           vty_out (vty, "%-20s %-20d %-20d %s", zebra_route_string(i), 
+                    rib_cnt[i], fib_cnt[i], VTY_NEWLINE);
+       }
+    }
 
-  vty_out (vty, "internal        %d%s", 0, VTY_NEWLINE);
-  vty_out (vty, "Total           %d%s", 0, VTY_NEWLINE);
+  vty_out (vty, "------%s", VTY_NEWLINE);
+  vty_out (vty, "%-20s %-20d %-20d %s", "Totals", rib_cnt[ZEBRA_ROUTE_TOTAL], 
+          fib_cnt[ZEBRA_ROUTE_TOTAL], VTY_NEWLINE);  
 }
 
 /* Show route summary.  */
@@ -1043,23 +1081,19 @@ DEFUN (show_ip_route_summary,
        "IP routing table\n"
        "Summary of all routes\n")
 {
-  struct vrf *vrf;
+  struct route_table *table;
 
-  /* Default table id is zero.  */
-  vrf = vrf_lookup (0);
-  if (! vrf)
-    {
-      vty_out (vty, "%% No Default-IP-Routing-Table%s", VTY_NEWLINE);
-      return CMD_WARNING;
-    }
+  table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
+  if (! table)
+    return CMD_SUCCESS;
 
-  zebra_show_ip_route (vty, vrf);
+  vty_show_ip_route_summary (vty, table);
 
   return CMD_SUCCESS;
 }
 
 /* Write IPv4 static route configuration. */
-int
+static int
 static_config_ipv4 (struct vty *vty)
 {
   struct route_node *rn;
@@ -1112,10 +1146,74 @@ static_config_ipv4 (struct vty *vty)
       }
   return write;
 }
-\f
+
+DEFUN (show_ip_protocol,
+       show_ip_protocol_cmd,
+       "show ip protocol",
+        SHOW_STR
+        IP_STR
+       "IP protocol filtering status\n")
+{
+    int i; 
+
+    vty_out(vty, "Protocol    : route-map %s", VTY_NEWLINE);
+    vty_out(vty, "------------------------%s", VTY_NEWLINE);
+    for (i=0;i<ZEBRA_ROUTE_MAX;i++)
+    {
+        if (proto_rm[AFI_IP][i])
+          vty_out (vty, "%-10s  : %-10s%s", zebra_route_string(i),
+                                       proto_rm[AFI_IP][i],
+                                       VTY_NEWLINE);
+        else
+          vty_out (vty, "%-10s  : none%s", zebra_route_string(i), VTY_NEWLINE);
+    }
+    if (proto_rm[AFI_IP][i])
+      vty_out (vty, "%-10s  : %-10s%s", "any", proto_rm[AFI_IP][i],
+                                       VTY_NEWLINE);
+    else
+      vty_out (vty, "%-10s  : none%s", "any", VTY_NEWLINE);
+
+    return CMD_SUCCESS;
+}
+
+/*
+ * Show IP mroute command to dump the BGP Multicast
+ * routing table
+ */
+DEFUN (show_ip_mroute,
+       show_ip_mroute_cmd,
+       "show ip mroute",
+       SHOW_STR
+       IP_STR
+       "IP Multicast routing table\n")
+{
+  struct route_table *table;
+  struct route_node *rn;
+  struct rib *rib;
+  int first = 1;
+
+  table = vrf_table (AFI_IP, SAFI_MULTICAST, 0);
+  if (! table)
+    return CMD_SUCCESS;
+
+  /* Show all IPv4 routes. */
+  for (rn = route_top (table); rn; rn = route_next (rn))
+    RNODE_FOREACH_RIB (rn, rib)
+      {
+       if (first)
+         {
+          vty_out (vty, SHOW_ROUTE_V4_HEADER);
+           first = 0;
+         }
+       vty_show_ip_route (vty, rn, rib);
+      }
+  return CMD_SUCCESS;
+}
+
+
 #ifdef HAVE_IPV6
 /* General fucntion for IPv6 static route. */
-int
+static int
 static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str,
                  const char *gate_str, const char *ifname,
                  const char *flag_str, const char *distance_str)
@@ -1420,21 +1518,22 @@ DEFUN (no_ipv6_route_ifname_flags_pref,
 }
 
 /* New RIB.  Detailed information for IPv6 route. */
-void
+static void
 vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn)
 {
   struct rib *rib;
-  struct nexthop *nexthop;
+  struct nexthop *nexthop, *tnexthop;
+  int recursing;
   char buf[BUFSIZ];
 
-  for (rib = rn->info; rib; rib = rib->next)
+  RNODE_FOREACH_RIB (rn, rib)
     {
       vty_out (vty, "Routing entry for %s/%d%s", 
               inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
               rn->p.prefixlen,
               VTY_NEWLINE);
-      vty_out (vty, "  Known via \"%s\"", route_type_str (rib->type));
-      vty_out (vty, ", distance %d, metric %d", rib->distance, rib->metric);
+      vty_out (vty, "  Known via \"%s\"", zebra_route_string (rib->type));
+      vty_out (vty, ", distance %u, metric %u", rib->distance, rib->metric);
       if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
        vty_out (vty, ", best");
       if (rib->refcnt)
@@ -1449,6 +1548,7 @@ vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn)
 #define ONE_WEEK_SECOND 60*60*24*7
       if (rib->type == ZEBRA_ROUTE_RIPNG
          || rib->type == ZEBRA_ROUTE_OSPF6
+         || rib->type == ZEBRA_ROUTE_BABEL
          || rib->type == ZEBRA_ROUTE_ISIS
          || rib->type == ZEBRA_ROUTE_BGP)
        {
@@ -1474,10 +1574,11 @@ vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn)
          vty_out (vty, " ago%s", VTY_NEWLINE);
        }
 
-      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+      for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
        {
-         vty_out (vty, "  %c",
-                  CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
+         vty_out (vty, "  %c%s",
+                  CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ',
+                  recursing ? "  " : "");
 
          switch (nexthop->type)
            {
@@ -1505,52 +1606,35 @@ vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn)
          if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
            vty_out (vty, " inactive");
 
+         if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
+           vty_out (vty, " onlink");
+
          if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
-           {
-             vty_out (vty, " (recursive");
-               
-             switch (nexthop->rtype)
-               {
-               case NEXTHOP_TYPE_IPV6:
-               case NEXTHOP_TYPE_IPV6_IFINDEX:
-               case NEXTHOP_TYPE_IPV6_IFNAME:
-                 vty_out (vty, " via %s)",
-                          inet_ntop (AF_INET6, &nexthop->rgate.ipv6,
-                                     buf, BUFSIZ));
-                 if (nexthop->rifindex)
-                   vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
-                 break;
-               case NEXTHOP_TYPE_IFINDEX:
-               case NEXTHOP_TYPE_IFNAME:
-                 vty_out (vty, " is directly connected, %s)",
-                          ifindex2ifname (nexthop->rifindex));
-                 break;
-               default:
-                 break;
-               }
-           }
+           vty_out (vty, " (recursive)");
+
          vty_out (vty, "%s", VTY_NEWLINE);
        }
       vty_out (vty, "%s", VTY_NEWLINE);
     }
 }
 
-void
+static void
 vty_show_ipv6_route (struct vty *vty, struct route_node *rn,
                     struct rib *rib)
 {
-  struct nexthop *nexthop;
+  struct nexthop *nexthop, *tnexthop;
+  int recursing;
   int len = 0;
   char buf[BUFSIZ];
 
   /* Nexthop information. */
-  for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+  for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
     {
       if (nexthop == rib->nexthop)
        {
          /* Prefix information. */
          len = vty_out (vty, "%c%c%c %s/%d",
-                        route_type_char (rib->type),
+                        zebra_route_char (rib->type),
                         CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)
                         ? '>' : ' ',
                         CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
@@ -1568,7 +1652,7 @@ vty_show_ipv6_route (struct vty *vty, struct route_node *rn,
        vty_out (vty, "  %c%*c",
                 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
                 ? '*' : ' ',
-                len - 3, ' ');
+                len - 3 + (2 * recursing), ' ');
 
       switch (nexthop->type)
        {
@@ -1597,29 +1681,7 @@ vty_show_ipv6_route (struct vty *vty, struct route_node *rn,
        vty_out (vty, " inactive");
 
       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
-       {
-         vty_out (vty, " (recursive");
-               
-         switch (nexthop->rtype)
-           {
-           case NEXTHOP_TYPE_IPV6:
-           case NEXTHOP_TYPE_IPV6_IFINDEX:
-           case NEXTHOP_TYPE_IPV6_IFNAME:
-             vty_out (vty, " via %s)",
-                      inet_ntop (AF_INET6, &nexthop->rgate.ipv6,
-                                 buf, BUFSIZ));
-             if (nexthop->rifindex)
-               vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
-             break;
-           case NEXTHOP_TYPE_IFINDEX:
-           case NEXTHOP_TYPE_IFNAME:
-             vty_out (vty, " is directly connected, %s)",
-                      ifindex2ifname (nexthop->rifindex));
-             break;
-           default:
-             break;
-           }
-       }
+       vty_out (vty, " (recursive)");
 
       if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
        vty_out (vty, ", bh");
@@ -1628,6 +1690,7 @@ vty_show_ipv6_route (struct vty *vty, struct route_node *rn,
       
       if (rib->type == ZEBRA_ROUTE_RIPNG
          || rib->type == ZEBRA_ROUTE_OSPF6
+         || rib->type == ZEBRA_ROUTE_BABEL
          || rib->type == ZEBRA_ROUTE_ISIS
          || rib->type == ZEBRA_ROUTE_BGP)
        {
@@ -1656,8 +1719,6 @@ vty_show_ipv6_route (struct vty *vty, struct route_node *rn,
     }
 }
 
-#define SHOW_ROUTE_V6_HEADER "Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3,%s       I - ISIS, B - BGP, * - FIB route.%s%s"
-
 DEFUN (show_ipv6_route,
        show_ipv6_route_cmd,
        "show ipv6 route",
@@ -1676,11 +1737,11 @@ DEFUN (show_ipv6_route,
 
   /* Show all IPv6 route. */
   for (rn = route_top (table); rn; rn = route_next (rn))
-    for (rib = rn->info; rib; rib = rib->next)
+    RNODE_FOREACH_RIB (rn, rib)
       {
        if (first)
          {
-           vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+           vty_out (vty, SHOW_ROUTE_V6_HEADER);
            first = 0;
          }
        vty_show_ipv6_route (vty, rn, rib);
@@ -1717,12 +1778,12 @@ DEFUN (show_ipv6_route_prefix_longer,
 
   /* Show matched type IPv6 routes. */
   for (rn = route_top (table); rn; rn = route_next (rn))
-    for (rib = rn->info; rib; rib = rib->next)
+    RNODE_FOREACH_RIB (rn, rib)
       if (prefix_match (&p, &rn->p))
        {
          if (first)
            {
-             vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+             vty_out (vty, SHOW_ROUTE_V6_HEADER);
              first = 0;
            }
          vty_show_ipv6_route (vty, rn, rib);
@@ -1732,17 +1793,11 @@ DEFUN (show_ipv6_route_prefix_longer,
 
 DEFUN (show_ipv6_route_protocol,
        show_ipv6_route_protocol_cmd,
-       "show ipv6 route (bgp|connected|isis|kernel|ospf6|ripng|static)",
+       "show ipv6 route " QUAGGA_IP6_REDIST_STR_ZEBRA,
        SHOW_STR
        IP_STR
        "IP routing table\n"
-       "Border Gateway Protocol (BGP)\n"
-       "Connected\n"
-       "ISO IS-IS (ISIS)\n"
-       "Kernel\n"
-       "Open Shortest Path First (OSPFv3)\n"
-       "Routing Information Protocol (RIPng)\n"
-       "Static routes\n")
+       QUAGGA_IP6_REDIST_HELP_STR_ZEBRA)
 {
   int type;
   struct route_table *table;
@@ -1750,21 +1805,8 @@ DEFUN (show_ipv6_route_protocol,
   struct rib *rib;
   int first = 1;
 
-  if (strncmp (argv[0], "b", 1) == 0)
-    type = ZEBRA_ROUTE_BGP;
-  else if (strncmp (argv[0], "c", 1) == 0)
-    type = ZEBRA_ROUTE_CONNECT;
-  else if (strncmp (argv[0], "k", 1) ==0)
-    type = ZEBRA_ROUTE_KERNEL;
-  else if (strncmp (argv[0], "o", 1) == 0)
-    type = ZEBRA_ROUTE_OSPF6;
-  else if (strncmp (argv[0], "i", 1) == 0)
-    type = ZEBRA_ROUTE_ISIS;
-  else if (strncmp (argv[0], "r", 1) == 0)
-    type = ZEBRA_ROUTE_RIPNG;
-  else if (strncmp (argv[0], "s", 1) == 0)
-    type = ZEBRA_ROUTE_STATIC;
-  else 
+  type = proto_redistnum (AFI_IP6, argv[0]);
+  if (type < 0)
     {
       vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
       return CMD_WARNING;
@@ -1776,12 +1818,12 @@ DEFUN (show_ipv6_route_protocol,
 
   /* Show matched type IPv6 routes. */
   for (rn = route_top (table); rn; rn = route_next (rn))
-    for (rib = rn->info; rib; rib = rib->next)
+    RNODE_FOREACH_RIB (rn, rib)
       if (rib->type == type)
        {
          if (first)
            {
-             vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+             vty_out (vty, SHOW_ROUTE_V6_HEADER);
              first = 0;
            }
          vty_show_ipv6_route (vty, rn, rib);
@@ -1865,9 +1907,63 @@ DEFUN (show_ipv6_route_prefix,
   return CMD_SUCCESS;
 }
 
+/* Show route summary.  */
+DEFUN (show_ipv6_route_summary,
+       show_ipv6_route_summary_cmd,
+       "show ipv6 route summary",
+       SHOW_STR
+       IP_STR
+       "IPv6 routing table\n"
+       "Summary of all IPv6 routes\n")
+{
+  struct route_table *table;
+
+  table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
+  if (! table)
+    return CMD_SUCCESS;
+
+  vty_show_ip_route_summary (vty, table);
+
+  return CMD_SUCCESS;
+}
+
+/*
+ * Show IPv6 mroute command.Used to dump
+ * the Multicast routing table.
+ */
+
+DEFUN (show_ipv6_mroute,
+       show_ipv6_mroute_cmd,
+       "show ipv6 mroute",
+       SHOW_STR
+       IP_STR
+       "IPv6 Multicast routing table\n")
+{
+  struct route_table *table;
+  struct route_node *rn;
+  struct rib *rib;
+  int first = 1;
+
+  table = vrf_table (AFI_IP6, SAFI_MULTICAST, 0);
+  if (! table)
+    return CMD_SUCCESS;
+
+  /* Show all IPv6 route. */
+  for (rn = route_top (table); rn; rn = route_next (rn))
+    RNODE_FOREACH_RIB (rn, rib)
+      {
+       if (first)
+         {
+          vty_out (vty, SHOW_ROUTE_V6_HEADER);
+           first = 0;
+         }
+       vty_show_ipv6_route (vty, rn, rib);
+      }
+  return CMD_SUCCESS;
+}
 
 /* Write IPv6 static route configuration. */
-int
+static int
 static_config_ipv6 (struct vty *vty)
 {
   struct route_node *rn;
@@ -1921,7 +2017,7 @@ static_config_ipv6 (struct vty *vty)
 #endif /* HAVE_IPV6 */
 
 /* Static ip route configuration write function. */
-int
+static int
 zebra_ip_config (struct vty *vty)
 {
   int write = 0;
@@ -1934,15 +2030,41 @@ zebra_ip_config (struct vty *vty)
   return write;
 }
 
+/* ip protocol configuration write function */
+static int config_write_protocol(struct vty *vty)
+{  
+  int i;
+
+  for (i=0;i<ZEBRA_ROUTE_MAX;i++)
+    {
+      if (proto_rm[AFI_IP][i])
+        vty_out (vty, "ip protocol %s route-map %s%s", zebra_route_string(i),
+                 proto_rm[AFI_IP][i], VTY_NEWLINE);
+    }
+  if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX])
+      vty_out (vty, "ip protocol %s route-map %s%s", "any",
+               proto_rm[AFI_IP][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
+
+  return 1;
+}   
+
+/* table node for protocol filtering */
+static struct cmd_node protocol_node = { PROTOCOL_NODE, "", 1 };
+
 /* IP node for static routes. */
-struct cmd_node ip_node = { IP_NODE,  "",  1 };
+static struct cmd_node ip_node = { IP_NODE,  "",  1 };
 
 /* Route VTY.  */
 void
-zebra_vty_route_init ()
+zebra_vty_init (void)
 {
   install_node (&ip_node, zebra_ip_config);
+  install_node (&protocol_node, config_write_protocol);
 
+  install_element (CONFIG_NODE, &ip_protocol_cmd);
+  install_element (CONFIG_NODE, &no_ip_protocol_cmd);
+  install_element (VIEW_NODE, &show_ip_protocol_cmd);
+  install_element (ENABLE_NODE, &show_ip_protocol_cmd);
   install_element (CONFIG_NODE, &ip_route_cmd);
   install_element (CONFIG_NODE, &ip_route_flags_cmd);
   install_element (CONFIG_NODE, &ip_route_flags2_cmd);
@@ -1973,17 +2095,18 @@ zebra_vty_route_init ()
   install_element (VIEW_NODE, &show_ip_route_prefix_longer_cmd);
   install_element (VIEW_NODE, &show_ip_route_protocol_cmd);
   install_element (VIEW_NODE, &show_ip_route_supernets_cmd);
+  install_element (VIEW_NODE, &show_ip_route_summary_cmd);
   install_element (ENABLE_NODE, &show_ip_route_cmd);
   install_element (ENABLE_NODE, &show_ip_route_addr_cmd);
   install_element (ENABLE_NODE, &show_ip_route_prefix_cmd);
   install_element (ENABLE_NODE, &show_ip_route_prefix_longer_cmd);
   install_element (ENABLE_NODE, &show_ip_route_protocol_cmd);
   install_element (ENABLE_NODE, &show_ip_route_supernets_cmd);
-
-#if 0
-  install_element (VIEW_NODE, &show_ip_route_summary_cmd);
   install_element (ENABLE_NODE, &show_ip_route_summary_cmd);
-#endif /* 0 */
+
+  install_element (VIEW_NODE, &show_ip_mroute_cmd);
+  install_element (ENABLE_NODE, &show_ip_mroute_cmd);
+
 
 #ifdef HAVE_IPV6
   install_element (CONFIG_NODE, &ipv6_route_cmd);
@@ -2003,6 +2126,7 @@ zebra_vty_route_init ()
   install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_cmd);
   install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_pref_cmd);
   install_element (VIEW_NODE, &show_ipv6_route_cmd);
+  install_element (VIEW_NODE, &show_ipv6_route_summary_cmd);
   install_element (VIEW_NODE, &show_ipv6_route_protocol_cmd);
   install_element (VIEW_NODE, &show_ipv6_route_addr_cmd);
   install_element (VIEW_NODE, &show_ipv6_route_prefix_cmd);
@@ -2012,11 +2136,9 @@ zebra_vty_route_init ()
   install_element (ENABLE_NODE, &show_ipv6_route_addr_cmd);
   install_element (ENABLE_NODE, &show_ipv6_route_prefix_cmd);
   install_element (ENABLE_NODE, &show_ipv6_route_prefix_longer_cmd);
-#endif /* HAVE_IPV6 */
-}
+  install_element (ENABLE_NODE, &show_ipv6_route_summary_cmd);
 
-void
-zebra_vty_init ()
-{
-  zebra_vty_route_init ();
+  install_element (VIEW_NODE, &show_ipv6_mroute_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mroute_cmd);
+#endif /* HAVE_IPV6 */
 }