zebra_vty.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:41k
源码类别:

网络

开发平台:

Unix_Linux

  1. /* Zebra VTY functions
  2.  * Copyright (C) 2002 Kunihiro Ishiguro
  3.  *
  4.  * This file is part of GNU Zebra.
  5.  *
  6.  * GNU Zebra is free software; you can redistribute it and/or modify it
  7.  * under the terms of the GNU General Public License as published by the
  8.  * Free Software Foundation; either version 2, or (at your option) any
  9.  * later version.
  10.  *
  11.  * GNU Zebra is distributed in the hope that it will be useful, but
  12.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with GNU Zebra; see the file COPYING.  If not, write to the 
  18.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
  19.  * Boston, MA 02111-1307, USA.  
  20.  */
  21. #include <zebra.h>
  22. #include "if.h"
  23. #include "prefix.h"
  24. #include "command.h"
  25. #include "table.h"
  26. #include "rib.h"
  27. /* Return route type string for VTY output.  */
  28. const char *
  29. route_type_str (u_char type)
  30. {
  31.   switch (type)
  32.     {
  33.     case ZEBRA_ROUTE_SYSTEM:
  34.       return "system";
  35.     case ZEBRA_ROUTE_KERNEL:
  36.       return "kernel";
  37.     case ZEBRA_ROUTE_CONNECT:
  38.       return "connected";
  39.     case ZEBRA_ROUTE_STATIC:
  40.       return "static";
  41.     case ZEBRA_ROUTE_RIP:
  42.       return "rip";
  43.     case ZEBRA_ROUTE_RIPNG:
  44.       return "rip";
  45.     case ZEBRA_ROUTE_OSPF:
  46.       return "ospf";
  47.     case ZEBRA_ROUTE_OSPF6:
  48.       return "ospf";
  49.     case ZEBRA_ROUTE_BGP:
  50.       return "bgp";
  51.     default:
  52.       return "unknown";
  53.     }
  54. };
  55. /* Return route type string for VTY output.  */
  56. const char
  57. route_type_char (u_char type)
  58. {
  59.   switch (type)
  60.     {
  61.     case ZEBRA_ROUTE_SYSTEM:
  62.       return 'S';
  63.     case ZEBRA_ROUTE_KERNEL:
  64.       return 'K';
  65.     case ZEBRA_ROUTE_CONNECT:
  66.       return 'C';
  67.     case ZEBRA_ROUTE_STATIC:
  68.       return 'S';
  69.     case ZEBRA_ROUTE_RIP:
  70.       return 'R';
  71.     case ZEBRA_ROUTE_RIPNG:
  72.       return 'R';
  73.     case ZEBRA_ROUTE_OSPF:
  74.       return 'O';
  75.     case ZEBRA_ROUTE_OSPF6:
  76.       return 'O';
  77.     case ZEBRA_ROUTE_BGP:
  78.       return 'B';
  79.     default:
  80.       return '?';
  81.     }
  82. };
  83. /* General fucntion for static route. */
  84. int
  85. zebra_static_ipv4 (struct vty *vty, int add_cmd,
  86.    char *dest_str, char *mask_str, char *gate_str,
  87.    char *distance_str)
  88. {
  89.   int ret;
  90.   u_char distance;
  91.   struct prefix p;
  92.   struct in_addr gate;
  93.   struct in_addr mask;
  94.   char *ifname;
  95.   
  96.   ret = str2prefix (dest_str, &p);
  97.   if (ret <= 0)
  98.     {
  99.       vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
  100.       return CMD_WARNING;
  101.     }
  102.   /* Cisco like mask notation. */
  103.   if (mask_str)
  104.     {
  105.       ret = inet_aton (mask_str, &mask);
  106.       if (ret == 0)
  107. {
  108.   vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
  109.   return CMD_WARNING;
  110. }
  111.       p.prefixlen = ip_masklen (mask);
  112.     }
  113.   /* Apply mask for given prefix. */
  114.   apply_mask (&p);
  115.   /* Administrative distance. */
  116.   if (distance_str)
  117.     distance = atoi (distance_str);
  118.   else
  119.     distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
  120.   /* Null0 static route.  */
  121.   if (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)
  122.     {
  123.       if (add_cmd)
  124. static_add_ipv4 (&p, NULL, NULL, distance, 0);
  125.       else
  126. static_delete_ipv4 (&p, NULL, NULL, distance, 0);
  127.       return CMD_SUCCESS;
  128.     }
  129.   /* When gateway is A.B.C.D format, gate is treated as nexthop
  130.      address other case gate is treated as interface name. */
  131.   ret = inet_aton (gate_str, &gate);
  132.   if (ret)
  133.     ifname = NULL;
  134.   else
  135.     ifname = gate_str;
  136.   if (add_cmd)
  137.     static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, distance, 0);
  138.   else
  139.     static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, distance, 0);
  140.   return CMD_SUCCESS;
  141. }
  142. /* Static route configuration.  */
  143. DEFUN (ip_route, 
  144.        ip_route_cmd,
  145.        "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0)",
  146.        IP_STR
  147.        "Establish static routesn"
  148.        "IP destination prefix (e.g. 10.0.0.0/8)n"
  149.        "IP gateway addressn"
  150.        "IP gateway interface namen"
  151.        "Null interfacen")
  152. {
  153.   return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL);
  154. }
  155. /* Mask as A.B.C.D format.  */
  156. DEFUN (ip_route_mask,
  157.        ip_route_mask_cmd,
  158.        "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0)",
  159.        IP_STR
  160.        "Establish static routesn"
  161.        "IP destination prefixn"
  162.        "IP destination prefix maskn"
  163.        "IP gateway addressn"
  164.        "IP gateway interface namen"
  165.        "Null interfacen")
  166. {
  167.   return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL);
  168. }
  169. /* Distance option value.  */
  170. DEFUN (ip_route_distance,
  171.        ip_route_distance_cmd,
  172.        "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>",
  173.        IP_STR
  174.        "Establish static routesn"
  175.        "IP destination prefix (e.g. 10.0.0.0/8)n"
  176.        "IP gateway addressn"
  177.        "IP gateway interface namen"
  178.        "Null interfacen"
  179.        "Distance value for this routen")
  180. {
  181.   return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2]);
  182. }
  183. DEFUN (ip_route_mask_distance,
  184.        ip_route_mask_distance_cmd,
  185.        "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) <1-255>",
  186.        IP_STR
  187.        "Establish static routesn"
  188.        "IP destination prefixn"
  189.        "IP destination prefix maskn"
  190.        "IP gateway addressn"
  191.        "IP gateway interface namen"
  192.        "Null interfacen"
  193.        "Distance value for this routen")
  194. {
  195.   return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3]);
  196. }
  197. DEFUN (no_ip_route, 
  198.        no_ip_route_cmd,
  199.        "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0)",
  200.        NO_STR
  201.        IP_STR
  202.        "Establish static routesn"
  203.        "IP destination prefix (e.g. 10.0.0.0/8)n"
  204.        "IP gateway addressn"
  205.        "IP gateway interface namen"
  206.        "Null interfacen")
  207. {
  208.   return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL);
  209. }
  210. DEFUN (no_ip_route_mask,
  211.        no_ip_route_mask_cmd,
  212.        "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0)",
  213.        NO_STR
  214.        IP_STR
  215.        "Establish static routesn"
  216.        "IP destination prefixn"
  217.        "IP destination prefix maskn"
  218.        "IP gateway addressn"
  219.        "IP gateway interface namen"
  220.        "Null interfacen")
  221. {
  222.   return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL);
  223. }
  224. DEFUN (no_ip_route_distance,
  225.        no_ip_route_distance_cmd,
  226.        "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>",
  227.        NO_STR
  228.        IP_STR
  229.        "Establish static routesn"
  230.        "IP destination prefix (e.g. 10.0.0.0/8)n"
  231.        "IP gateway addressn"
  232.        "IP gateway interface namen"
  233.        "Null interfacen"
  234.        "Distance value for this routen")
  235. {
  236.   return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2]);
  237. }
  238. DEFUN (no_ip_route_mask_distance,
  239.        no_ip_route_mask_distance_cmd,
  240.        "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) <1-255>",
  241.        NO_STR
  242.        IP_STR
  243.        "Establish static routesn"
  244.        "IP destination prefixn"
  245.        "IP destination prefix maskn"
  246.        "IP gateway addressn"
  247.        "IP gateway interface namen"
  248.        "Null interfacen"
  249.        "Distance value for this routen")
  250. {
  251.   return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3]);
  252. }
  253. /* New RIB.  Detailed information for IPv4 route. */
  254. void
  255. vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
  256. {
  257.   struct rib *rib;
  258.   struct nexthop *nexthop;
  259.   for (rib = rn->info; rib; rib = rib->next)
  260.     {
  261.       vty_out (vty, "Routing entry for %s/%d%s", 
  262.        inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
  263.        VTY_NEWLINE);
  264.       vty_out (vty, "  Known via "%s"", route_type_str (rib->type));
  265.       vty_out (vty, ", distance %d, metric %d", rib->distance, rib->metric);
  266.       if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
  267. vty_out (vty, ", best");
  268.       if (rib->refcnt)
  269. vty_out (vty, ", refcnt %ld", rib->refcnt);
  270.       vty_out (vty, "%s", VTY_NEWLINE);
  271. #define ONE_DAY_SECOND 60*60*24
  272. #define ONE_WEEK_SECOND 60*60*24*7
  273.       if (rib->type == ZEBRA_ROUTE_RIP
  274.   || rib->type == ZEBRA_ROUTE_OSPF
  275.   || rib->type == ZEBRA_ROUTE_BGP)
  276. {
  277.   time_t uptime;
  278.   struct tm *tm;
  279.   uptime = time (NULL);
  280.   uptime -= rib->uptime;
  281.   tm = gmtime (&uptime);
  282.   vty_out (vty, "  Last update ");
  283.   if (uptime < ONE_DAY_SECOND)
  284.     vty_out (vty,  "%02d:%02d:%02d", 
  285.      tm->tm_hour, tm->tm_min, tm->tm_sec);
  286.   else if (uptime < ONE_WEEK_SECOND)
  287.     vty_out (vty, "%dd%02dh%02dm", 
  288.      tm->tm_yday, tm->tm_hour, tm->tm_min);
  289.   else
  290.     vty_out (vty, "%02dw%dd%02dh", 
  291.      tm->tm_yday/7,
  292.      tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
  293.   vty_out (vty, " ago%s", VTY_NEWLINE);
  294. }
  295.       for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
  296. {
  297.   vty_out (vty, "  %c",
  298.    CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
  299.   switch (nexthop->type)
  300.     {
  301.     case NEXTHOP_TYPE_IPV4:
  302.     case NEXTHOP_TYPE_IPV4_IFINDEX:
  303.       vty_out (vty, " %s", inet_ntoa (nexthop->gate.ipv4));
  304.       if (nexthop->ifindex)
  305. vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex));
  306.       break;
  307.     case NEXTHOP_TYPE_IFINDEX:
  308.       vty_out (vty, " directly connected, %s",
  309.        ifindex2ifname (nexthop->ifindex));
  310.       break;
  311.     case NEXTHOP_TYPE_IFNAME:
  312.       vty_out (vty, " directly connected, %s", nexthop->ifname);
  313.       break;
  314.     case NEXTHOP_TYPE_BLACKHOLE:
  315.       vty_out (vty, " directly connected, via Null0");
  316.       break;
  317.     default:
  318.       break;
  319.     }
  320.   if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
  321.     vty_out (vty, " inactive");
  322.   if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
  323.     {
  324.       vty_out (vty, " (recursive");
  325.       switch (nexthop->rtype)
  326. {
  327. case NEXTHOP_TYPE_IPV4:
  328. case NEXTHOP_TYPE_IPV4_IFINDEX:
  329.   vty_out (vty, " via %s)", inet_ntoa (nexthop->rgate.ipv4));
  330.   break;
  331. case NEXTHOP_TYPE_IFINDEX:
  332. case NEXTHOP_TYPE_IFNAME:
  333.   vty_out (vty, " is directly connected, %s)",
  334.    ifindex2ifname (nexthop->rifindex));
  335.   break;
  336. default:
  337.   break;
  338. }
  339.     }
  340.   vty_out (vty, "%s", VTY_NEWLINE);
  341. }
  342.       vty_out (vty, "%s", VTY_NEWLINE);
  343.     }
  344. }
  345. void
  346. vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
  347. {
  348.   struct nexthop *nexthop;
  349.   int len = 0;
  350.   char buf[BUFSIZ];
  351.   /* Nexthop information. */
  352.   for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
  353.     {
  354.       if (nexthop == rib->nexthop)
  355. {
  356.   /* Prefix information. */
  357.   len = vty_out (vty, "%c%c%c %s/%d",
  358.  route_type_char (rib->type),
  359.  CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)
  360.  ? '>' : ' ',
  361.  CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
  362.  ? '*' : ' ',
  363.  inet_ntop (AF_INET, &rn->p.u.prefix, buf, BUFSIZ),
  364.  rn->p.prefixlen);
  365.   /* Distance and metric display. */
  366.   if (rib->type != ZEBRA_ROUTE_CONNECT 
  367.       && rib->type != ZEBRA_ROUTE_KERNEL)
  368.     len += vty_out (vty, " [%d/%d]", rib->distance,
  369.     rib->metric);
  370. }
  371.       else
  372. vty_out (vty, "  %c%*c",
  373.  CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
  374.  ? '*' : ' ',
  375.  len - 3, ' ');
  376.       switch (nexthop->type)
  377. {
  378. case NEXTHOP_TYPE_IPV4:
  379. case NEXTHOP_TYPE_IPV4_IFINDEX:
  380.   vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4));
  381.   if (nexthop->ifindex)
  382.     vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex));
  383.   break;
  384. case NEXTHOP_TYPE_IFINDEX:
  385.   vty_out (vty, " is directly connected, %s",
  386.    ifindex2ifname (nexthop->ifindex));
  387.   break;
  388. case NEXTHOP_TYPE_IFNAME:
  389.   vty_out (vty, " is directly connected, %s", nexthop->ifname);
  390.   break;
  391. case NEXTHOP_TYPE_BLACKHOLE:
  392.   vty_out (vty, " is directly connected, Null0");
  393. default:
  394.   break;
  395. }
  396.       if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
  397. vty_out (vty, " inactive");
  398.       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
  399. {
  400.   vty_out (vty, " (recursive");
  401.   switch (nexthop->rtype)
  402.     {
  403.     case NEXTHOP_TYPE_IPV4:
  404.     case NEXTHOP_TYPE_IPV4_IFINDEX:
  405.       vty_out (vty, " via %s)", inet_ntoa (nexthop->rgate.ipv4));
  406.       break;
  407.     case NEXTHOP_TYPE_IFINDEX:
  408.     case NEXTHOP_TYPE_IFNAME:
  409.       vty_out (vty, " is directly connected, %s)",
  410.        ifindex2ifname (nexthop->rifindex));
  411.       break;
  412.     default:
  413.       break;
  414.     }
  415. }
  416.       if (rib->type == ZEBRA_ROUTE_RIP
  417.   || rib->type == ZEBRA_ROUTE_OSPF
  418.   || rib->type == ZEBRA_ROUTE_BGP)
  419. {
  420.   time_t uptime;
  421.   struct tm *tm;
  422.   uptime = time (NULL);
  423.   uptime -= rib->uptime;
  424.   tm = gmtime (&uptime);
  425. #define ONE_DAY_SECOND 60*60*24
  426. #define ONE_WEEK_SECOND 60*60*24*7
  427.   if (uptime < ONE_DAY_SECOND)
  428.     vty_out (vty,  ", %02d:%02d:%02d", 
  429.      tm->tm_hour, tm->tm_min, tm->tm_sec);
  430.   else if (uptime < ONE_WEEK_SECOND)
  431.     vty_out (vty, ", %dd%02dh%02dm", 
  432.      tm->tm_yday, tm->tm_hour, tm->tm_min);
  433.   else
  434.     vty_out (vty, ", %02dw%dd%02dh", 
  435.      tm->tm_yday/7,
  436.      tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
  437. }
  438.       vty_out (vty, "%s", VTY_NEWLINE);
  439.     }
  440. }
  441. #define SHOW_ROUTE_V4_HEADER "Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,%s       B - BGP, > - selected route, * - FIB route%s%s"
  442. DEFUN (show_ip_route,
  443.        show_ip_route_cmd,
  444.        "show ip route",
  445.        SHOW_STR
  446.        IP_STR
  447.        "IP routing tablen")
  448. {
  449.   struct route_table *table;
  450.   struct route_node *rn;
  451.   struct rib *rib;
  452.   int first = 1;
  453.   table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
  454.   if (! table)
  455.     return CMD_SUCCESS;
  456.   /* Show all IPv4 routes. */
  457.   for (rn = route_top (table); rn; rn = route_next (rn))
  458.     for (rib = rn->info; rib; rib = rib->next)
  459.       {
  460. if (first)
  461.   {
  462.     vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE,
  463.      VTY_NEWLINE);
  464.     first = 0;
  465.   }
  466. vty_show_ip_route (vty, rn, rib);
  467.       }
  468.   return CMD_SUCCESS;
  469. }
  470. DEFUN (show_ip_route_prefix_longer,
  471.        show_ip_route_prefix_longer_cmd,
  472.        "show ip route A.B.C.D/M longer-prefixes",
  473.        SHOW_STR
  474.        IP_STR
  475.        "IP routing tablen"
  476.        "IP prefix <network>/<length>, e.g., 35.0.0.0/8n"
  477.        "Show route matching the specified Network/Mask pair onlyn")
  478. {
  479.   struct route_table *table;
  480.   struct route_node *rn;
  481.   struct rib *rib;
  482.   struct prefix p;
  483.   int ret;
  484.   int first = 1;
  485.   ret = str2prefix (argv[0], &p);
  486.   if (! ret)
  487.     {
  488.       vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
  489.       return CMD_WARNING;
  490.     }
  491.   
  492.   table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
  493.   if (! table)
  494.     return CMD_SUCCESS;
  495.   /* Show matched type IPv4 routes. */
  496.   for (rn = route_top (table); rn; rn = route_next (rn))
  497.     for (rib = rn->info; rib; rib = rib->next)
  498.       if (prefix_match (&p, &rn->p))
  499. {
  500.   if (first)
  501.     {
  502.       vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE,
  503.        VTY_NEWLINE, VTY_NEWLINE);
  504.       first = 0;
  505.     }
  506.   vty_show_ip_route (vty, rn, rib);
  507. }
  508.   return CMD_SUCCESS;
  509. }
  510. DEFUN (show_ip_route_supernets,
  511.        show_ip_route_supernets_cmd,
  512.        "show ip route supernets-only",
  513.        SHOW_STR
  514.        IP_STR
  515.        "IP routing tablen"
  516.        "Show supernet entries onlyn")
  517. {
  518.   struct route_table *table;
  519.   struct route_node *rn;
  520.   struct rib *rib;
  521.   u_int32_t addr; 
  522.   int first = 1;
  523.   table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
  524.   if (! table)
  525.     return CMD_SUCCESS;
  526.   /* Show matched type IPv4 routes. */
  527.   for (rn = route_top (table); rn; rn = route_next (rn))
  528.     for (rib = rn->info; rib; rib = rib->next)
  529.       {
  530. addr = ntohl (rn->p.u.prefix4.s_addr);
  531. if ((IN_CLASSC (addr) && rn->p.prefixlen < 24)
  532.    || (IN_CLASSB (addr) && rn->p.prefixlen < 16)
  533.    || (IN_CLASSA (addr) && rn->p.prefixlen < 8)) 
  534.   {
  535.     if (first)
  536.       {
  537. vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE,
  538.  VTY_NEWLINE, VTY_NEWLINE);
  539. first = 0;
  540.       }
  541.     vty_show_ip_route (vty, rn, rib);
  542.   }
  543.       }
  544.   return CMD_SUCCESS;
  545. }
  546. DEFUN (show_ip_route_protocol,
  547.        show_ip_route_protocol_cmd,
  548.        "show ip route (bgp|connected|kernel|ospf|rip|static)",
  549.        SHOW_STR
  550.        IP_STR
  551.        "IP routing tablen"
  552.        "Border Gateway Protocol (BGP)n"
  553.        "Connectedn"
  554.        "Kerneln"
  555.        "Open Shortest Path First (OSPF)n"
  556.        "Routing Information Protocol (RIP)n"
  557.        "Static routesn")
  558. {
  559.   int type;
  560.   struct route_table *table;
  561.   struct route_node *rn;
  562.   struct rib *rib;
  563.   int first = 1;
  564.   if (strncmp (argv[0], "b", 1) == 0)
  565.     type = ZEBRA_ROUTE_BGP;
  566.   else if (strncmp (argv[0], "c", 1) == 0)
  567.     type = ZEBRA_ROUTE_CONNECT;
  568.   else if (strncmp (argv[0], "k", 1) ==0)
  569.     type = ZEBRA_ROUTE_KERNEL;
  570.   else if (strncmp (argv[0], "o", 1) == 0)
  571.     type = ZEBRA_ROUTE_OSPF;
  572.   else if (strncmp (argv[0], "r", 1) == 0)
  573.     type = ZEBRA_ROUTE_RIP;
  574.   else if (strncmp (argv[0], "s", 1) == 0)
  575.     type = ZEBRA_ROUTE_STATIC;
  576.   else 
  577.     {
  578.       vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
  579.       return CMD_WARNING;
  580.     }
  581.   
  582.   table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
  583.   if (! table)
  584.     return CMD_SUCCESS;
  585.   /* Show matched type IPv4 routes. */
  586.   for (rn = route_top (table); rn; rn = route_next (rn))
  587.     for (rib = rn->info; rib; rib = rib->next)
  588.       if (rib->type == type)
  589. {
  590.   if (first)
  591.     {
  592.       vty_out (vty, SHOW_ROUTE_V4_HEADER,
  593.        VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
  594.       first = 0;
  595.     }
  596.   vty_show_ip_route (vty, rn, rib);
  597. }
  598.   return CMD_SUCCESS;
  599. }
  600. DEFUN (show_ip_route_addr,
  601.        show_ip_route_addr_cmd,
  602.        "show ip route A.B.C.D",
  603.        SHOW_STR
  604.        IP_STR
  605.        "IP routing tablen"
  606.        "Network in the IP routing table to displayn")
  607. {
  608.   int ret;
  609.   struct prefix_ipv4 p;
  610.   struct route_table *table;
  611.   struct route_node *rn;
  612.   ret = str2prefix_ipv4 (argv[0], &p);
  613.   if (ret <= 0)
  614.     {
  615.       vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE);
  616.       return CMD_WARNING;
  617.     }
  618.   table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
  619.   if (! table)
  620.     return CMD_SUCCESS;
  621.   rn = route_node_match (table, (struct prefix *) &p);
  622.   if (! rn)
  623.     {
  624.       vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
  625.       return CMD_WARNING;
  626.     }
  627.   vty_show_ip_route_detail (vty, rn);
  628.   route_unlock_node (rn);
  629.   return CMD_SUCCESS;
  630. }
  631. DEFUN (show_ip_route_prefix,
  632.        show_ip_route_prefix_cmd,
  633.        "show ip route A.B.C.D/M",
  634.        SHOW_STR
  635.        IP_STR
  636.        "IP routing tablen"
  637.        "IP prefix <network>/<length>, e.g., 35.0.0.0/8n")
  638. {
  639.   int ret;
  640.   struct prefix_ipv4 p;
  641.   struct route_table *table;
  642.   struct route_node *rn;
  643.   ret = str2prefix_ipv4 (argv[0], &p);
  644.   if (ret <= 0)
  645.     {
  646.       vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE);
  647.       return CMD_WARNING;
  648.     }
  649.   table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
  650.   if (! table)
  651.     return CMD_SUCCESS;
  652.   rn = route_node_match (table, (struct prefix *) &p);
  653.   if (! rn || rn->p.prefixlen != p.prefixlen)
  654.     {
  655.       vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
  656.       return CMD_WARNING;
  657.     }
  658.   vty_show_ip_route_detail (vty, rn);
  659.   route_unlock_node (rn);
  660.   return CMD_SUCCESS;
  661. }
  662. void
  663. zebra_show_ip_route (struct vty *vty, struct vrf *vrf)
  664. {
  665.   vty_out (vty, "IP routing table name is %s(%d)%s",
  666.    vrf->name ? vrf->name : "", vrf->id, VTY_NEWLINE);
  667.   vty_out (vty, "Route Source    Networks%s", VTY_NEWLINE);
  668.   vty_out (vty, "connected       %d%s", 0, VTY_NEWLINE);
  669.   vty_out (vty, "static          %d%s", 0, VTY_NEWLINE);
  670.   vty_out (vty, "rip             %d%s", 0, VTY_NEWLINE);
  671.   vty_out (vty, "bgp             %d%s", 0, VTY_NEWLINE);
  672.   vty_out (vty, " External: %d Internal: %d Local: %d%s",
  673.    0, 0, 0, VTY_NEWLINE);
  674.   vty_out (vty, "ospf            %d%s", 0, VTY_NEWLINE);
  675.   vty_out (vty,
  676.    "  Intra-area: %d Inter-area: %d External-1: %d External-2: %d%s",
  677.    0, 0, 0, 0, VTY_NEWLINE);
  678.   vty_out (vty, "  NSSA External-1: %d NSSA External-2: %d%s",
  679.    0, 0, VTY_NEWLINE);
  680.   vty_out (vty, "internal        %d%s", 0, VTY_NEWLINE);
  681.   vty_out (vty, "Total           %d%s", 0, VTY_NEWLINE);
  682. }
  683. /* Show route summary.  */
  684. DEFUN (show_ip_route_summary,
  685.        show_ip_route_summary_cmd,
  686.        "show ip route summary",
  687.        SHOW_STR
  688.        IP_STR
  689.        "IP routing tablen"
  690.        "Summary of all routesn")
  691. {
  692.   struct vrf *vrf;
  693.   /* Default table id is zero.  */
  694.   vrf = vrf_lookup (0);
  695.   if (! vrf)
  696.     {
  697.       vty_out (vty, "%% No Default-IP-Routing-Table%s", VTY_NEWLINE);
  698.       return CMD_WARNING;
  699.     }
  700.   zebra_show_ip_route (vty, vrf);
  701.   return CMD_SUCCESS;
  702. }
  703. /* Write IPv4 static route configuration. */
  704. int
  705. static_config_ipv4 (struct vty *vty)
  706. {
  707.   struct route_node *rn;
  708.   struct static_ipv4 *si;  
  709.   struct route_table *stable;
  710.   int write;
  711.   write = 0;
  712.   /* Lookup table.  */
  713.   stable = vrf_static_table (AFI_IP, SAFI_UNICAST, 0);
  714.   if (! stable)
  715.     return -1;
  716.   for (rn = route_top (stable); rn; rn = route_next (rn))
  717.     for (si = rn->info; si; si = si->next)
  718.       {
  719. vty_out (vty, "ip route %s/%d", inet_ntoa (rn->p.u.prefix4),
  720.  rn->p.prefixlen);
  721. switch (si->type)
  722.   {
  723.   case STATIC_IPV4_GATEWAY:
  724.     vty_out (vty, " %s", inet_ntoa (si->gate.ipv4));
  725.     break;
  726.   case STATIC_IPV4_IFNAME:
  727.     vty_out (vty, " %s", si->gate.ifname);
  728.     break;
  729.   case STATIC_IPV4_BLACKHOLE:
  730.     vty_out (vty, " Null0");
  731.     break;
  732.   }
  733. if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
  734.   vty_out (vty, " %d", si->distance);
  735. vty_out (vty, "%s", VTY_NEWLINE);
  736. write = 1;
  737.       }
  738.   return write;
  739. }
  740. #ifdef HAVE_IPV6
  741. /* General fucntion for IPv6 static route. */
  742. int
  743. static_ipv6_func (struct vty *vty, int add_cmd, char *dest_str,
  744.   char *gate_str, char *ifname, char *distance_str)
  745. {
  746.   int ret;
  747.   u_char distance;
  748.   struct prefix p;
  749.   struct in6_addr *gate = NULL;
  750.   struct in6_addr gate_addr;
  751.   u_char type = 0;
  752.   int table = 0;
  753.   
  754.   ret = str2prefix (dest_str, &p);
  755.   if (ret <= 0)
  756.     {
  757.       vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
  758.       return CMD_WARNING;
  759.     }
  760.   /* Apply mask for given prefix. */
  761.   apply_mask (&p);
  762.   /* Administrative distance. */
  763.   if (distance_str)
  764.     distance = atoi (distance_str);
  765.   else
  766.     distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
  767.   /* Null0 static route.  */
  768.   if (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)
  769.     {
  770.       type = STATIC_IPV6_BLACKHOLE;
  771.       if (add_cmd)
  772. static_add_ipv6 (&p, type, NULL, NULL, distance, 0);
  773.       else
  774. static_delete_ipv6 (&p, type, NULL, NULL, distance, 0);
  775.       return CMD_SUCCESS;
  776.     }
  777.   /* When gateway is valid IPv6 addrees, then gate is treated as
  778.      nexthop address other case gate is treated as interface name. */
  779.   ret = inet_pton (AF_INET6, gate_str, &gate_addr);
  780.   if (ifname)
  781.     {
  782.       /* When ifname is specified.  It must be come with gateway
  783.          address. */
  784.       if (ret != 1)
  785. {
  786.   vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
  787.   return CMD_WARNING;
  788. }
  789.       type = STATIC_IPV6_GATEWAY_IFNAME;
  790.       gate = &gate_addr;
  791.     }
  792.   else
  793.     {
  794.       if (ret == 1)
  795. {
  796.   type = STATIC_IPV6_GATEWAY;
  797.   gate = &gate_addr;
  798. }
  799.       else
  800. {
  801.   type = STATIC_IPV6_IFNAME;
  802.   ifname = gate_str;
  803. }
  804.     }
  805.   if (add_cmd)
  806.     static_add_ipv6 (&p, type, gate, ifname, distance, table);
  807.   else
  808.     static_delete_ipv6 (&p, type, gate, ifname, distance, table);
  809.   return CMD_SUCCESS;
  810. }
  811. DEFUN (ipv6_route,
  812.        ipv6_route_cmd,
  813.        "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE|null0)",
  814.        IP_STR
  815.        "Establish static routesn"
  816.        "IPv6 destination prefix (e.g. 3ffe:506::/32)n"
  817.        "IPv6 gateway addressn"
  818.        "IPv6 gateway interface namen")
  819. {
  820.   return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL);
  821. }
  822. DEFUN (ipv6_route_ifname,
  823.        ipv6_route_ifname_cmd,
  824.        "ipv6 route X:X::X:X/M X:X::X:X INTERFACE",
  825.        IP_STR
  826.        "Establish static routesn"
  827.        "IPv6 destination prefix (e.g. 3ffe:506::/32)n"
  828.        "IPv6 gateway addressn"
  829.        "IPv6 gateway interface namen")
  830. {
  831.   return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL);
  832. }
  833. DEFUN (ipv6_route_pref,
  834.        ipv6_route_pref_cmd,
  835.        "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE|null0) <1-255>",
  836.        IP_STR
  837.        "Establish static routesn"
  838.        "IPv6 destination prefix (e.g. 3ffe:506::/32)n"
  839.        "IPv6 gateway addressn"
  840.        "IPv6 gateway interface namen"
  841.        "Distance value for this prefixn")
  842. {
  843.   return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2]);
  844. }
  845. DEFUN (ipv6_route_ifname_pref,
  846.        ipv6_route_ifname_pref_cmd,
  847.        "ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>",
  848.        IP_STR
  849.        "Establish static routesn"
  850.        "IPv6 destination prefix (e.g. 3ffe:506::/32)n"
  851.        "IPv6 gateway addressn"
  852.        "IPv6 gateway interface namen"
  853.        "Distance value for this prefixn")
  854. {
  855.   return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3]);
  856. }
  857. DEFUN (no_ipv6_route,
  858.        no_ipv6_route_cmd,
  859.        "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE|null0)",
  860.        NO_STR
  861.        IP_STR
  862.        "Establish static routesn"
  863.        "IPv6 destination prefix (e.g. 3ffe:506::/32)n"
  864.        "IPv6 gateway addressn"
  865.        "IPv6 gateway interface namen")
  866. {
  867.   return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL);
  868. }
  869. DEFUN (no_ipv6_route_ifname,
  870.        no_ipv6_route_ifname_cmd,
  871.        "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE",
  872.        NO_STR
  873.        IP_STR
  874.        "Establish static routesn"
  875.        "IPv6 destination prefix (e.g. 3ffe:506::/32)n"
  876.        "IPv6 gateway addressn"
  877.        "IPv6 gateway interface namen")
  878. {
  879.   return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL);
  880. }
  881. DEFUN (no_ipv6_route_pref,
  882.        no_ipv6_route_pref_cmd,
  883.        "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE|null0) <1-255>",
  884.        NO_STR
  885.        IP_STR
  886.        "Establish static routesn"
  887.        "IPv6 destination prefix (e.g. 3ffe:506::/32)n"
  888.        "IPv6 gateway addressn"
  889.        "IPv6 gateway interface namen"
  890.        "Distance value for this prefixn")
  891. {
  892.   return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2]);
  893. }
  894. DEFUN (no_ipv6_route_ifname_pref,
  895.        no_ipv6_route_ifname_pref_cmd,
  896.        "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>",
  897.        NO_STR
  898.        IP_STR
  899.        "Establish static routesn"
  900.        "IPv6 destination prefix (e.g. 3ffe:506::/32)n"
  901.        "IPv6 gateway addressn"
  902.        "IPv6 gateway interface namen"
  903.        "Distance value for this prefixn")
  904. {
  905.   return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3]);
  906. }
  907. /* New RIB.  Detailed information for IPv6 route. */
  908. void
  909. vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn)
  910. {
  911.   struct rib *rib;
  912.   struct nexthop *nexthop;
  913.   char buf[BUFSIZ];
  914.   for (rib = rn->info; rib; rib = rib->next)
  915.     {
  916.       vty_out (vty, "Routing entry for %s/%d%s", 
  917.        inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
  918.        rn->p.prefixlen,
  919.        VTY_NEWLINE);
  920.       vty_out (vty, "  Known via "%s"", route_type_str (rib->type));
  921.       vty_out (vty, ", distance %d, metric %d", rib->distance, rib->metric);
  922.       if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
  923. vty_out (vty, ", best");
  924.       if (rib->refcnt)
  925. vty_out (vty, ", refcnt %ld", rib->refcnt);
  926.       vty_out (vty, "%s", VTY_NEWLINE);
  927. #define ONE_DAY_SECOND 60*60*24
  928. #define ONE_WEEK_SECOND 60*60*24*7
  929.       if (rib->type == ZEBRA_ROUTE_RIPNG
  930.   || rib->type == ZEBRA_ROUTE_OSPF6
  931.   || rib->type == ZEBRA_ROUTE_BGP)
  932. {
  933.   time_t uptime;
  934.   struct tm *tm;
  935.   uptime = time (NULL);
  936.   uptime -= rib->uptime;
  937.   tm = gmtime (&uptime);
  938.   vty_out (vty, "  Last update ");
  939.   if (uptime < ONE_DAY_SECOND)
  940.     vty_out (vty,  "%02d:%02d:%02d", 
  941.      tm->tm_hour, tm->tm_min, tm->tm_sec);
  942.   else if (uptime < ONE_WEEK_SECOND)
  943.     vty_out (vty, "%dd%02dh%02dm", 
  944.      tm->tm_yday, tm->tm_hour, tm->tm_min);
  945.   else
  946.     vty_out (vty, "%02dw%dd%02dh", 
  947.      tm->tm_yday/7,
  948.      tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
  949.   vty_out (vty, " ago%s", VTY_NEWLINE);
  950. }
  951.       for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
  952. {
  953.   vty_out (vty, "  %c",
  954.    CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
  955.   switch (nexthop->type)
  956.     {
  957.     case NEXTHOP_TYPE_IPV6:
  958.     case NEXTHOP_TYPE_IPV6_IFINDEX:
  959.     case NEXTHOP_TYPE_IPV6_IFNAME:
  960.       vty_out (vty, " %s",
  961.        inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
  962.       if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
  963. vty_out (vty, ", %s", nexthop->ifname);
  964.       else if (nexthop->ifindex)
  965. vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex));
  966.       break;
  967.     case NEXTHOP_TYPE_IFINDEX:
  968.       vty_out (vty, " directly connected, %s",
  969.        ifindex2ifname (nexthop->ifindex));
  970.       break;
  971.     case NEXTHOP_TYPE_IFNAME:
  972.       vty_out (vty, " directly connected, %s",
  973.        nexthop->ifname);
  974.       break;
  975.     case NEXTHOP_TYPE_BLACKHOLE:
  976.       vty_out (vty, " directly connected, via Null0");
  977.       break;
  978.     default:
  979.       break;
  980.     }
  981.   if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
  982.     vty_out (vty, " inactive");
  983.   if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
  984.     {
  985.       vty_out (vty, " (recursive");
  986.       switch (nexthop->rtype)
  987. {
  988. case NEXTHOP_TYPE_IPV6:
  989. case NEXTHOP_TYPE_IPV6_IFINDEX:
  990. case NEXTHOP_TYPE_IPV6_IFNAME:
  991.   vty_out (vty, " via %s)",
  992.    inet_ntop (AF_INET6, &nexthop->rgate.ipv6,
  993.       buf, BUFSIZ));
  994.   if (nexthop->rifindex)
  995.     vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
  996.   break;
  997. case NEXTHOP_TYPE_IFINDEX:
  998. case NEXTHOP_TYPE_IFNAME:
  999.   vty_out (vty, " is directly connected, %s)",
  1000.    ifindex2ifname (nexthop->rifindex));
  1001.   break;
  1002. default:
  1003.   break;
  1004. }
  1005.     }
  1006.   vty_out (vty, "%s", VTY_NEWLINE);
  1007. }
  1008.       vty_out (vty, "%s", VTY_NEWLINE);
  1009.     }
  1010. }
  1011. void
  1012. vty_show_ipv6_route (struct vty *vty, struct route_node *rn,
  1013.      struct rib *rib)
  1014. {
  1015.   struct nexthop *nexthop;
  1016.   int len = 0;
  1017.   char buf[BUFSIZ];
  1018.   /* Nexthop information. */
  1019.   for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
  1020.     {
  1021.       if (nexthop == rib->nexthop)
  1022. {
  1023.   /* Prefix information. */
  1024.   len = vty_out (vty, "%c%c%c %s/%d",
  1025.  route_type_char (rib->type),
  1026.  CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)
  1027.  ? '>' : ' ',
  1028.  CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
  1029.  ? '*' : ' ',
  1030.  inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
  1031.  rn->p.prefixlen);
  1032.   /* Distance and metric display. */
  1033.   if (rib->type != ZEBRA_ROUTE_CONNECT 
  1034.       && rib->type != ZEBRA_ROUTE_KERNEL)
  1035.     len += vty_out (vty, " [%d/%d]", rib->distance,
  1036.     rib->metric);
  1037. }
  1038.       else
  1039. vty_out (vty, "  %c%*c",
  1040.  CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
  1041.  ? '*' : ' ',
  1042.  len - 3, ' ');
  1043.       switch (nexthop->type)
  1044. {
  1045. case NEXTHOP_TYPE_IPV6:
  1046. case NEXTHOP_TYPE_IPV6_IFINDEX:
  1047. case NEXTHOP_TYPE_IPV6_IFNAME:
  1048.   vty_out (vty, " via %s",
  1049.    inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
  1050.   if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
  1051.     vty_out (vty, ", %s", nexthop->ifname);
  1052.   else if (nexthop->ifindex)
  1053.     vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex));
  1054.   break;
  1055. case NEXTHOP_TYPE_IFINDEX:
  1056.   vty_out (vty, " is directly connected, %s",
  1057.    ifindex2ifname (nexthop->ifindex));
  1058.   break;
  1059. case NEXTHOP_TYPE_IFNAME:
  1060.   vty_out (vty, " is directly connected, %s",
  1061.    nexthop->ifname);
  1062.   break;
  1063. case NEXTHOP_TYPE_BLACKHOLE:
  1064.   vty_out (vty, " is directly connected, Null0");
  1065. default:
  1066.   break;
  1067. }
  1068.       if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
  1069. vty_out (vty, " inactive");
  1070.       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
  1071. {
  1072.   vty_out (vty, " (recursive");
  1073.   switch (nexthop->rtype)
  1074.     {
  1075.     case NEXTHOP_TYPE_IPV6:
  1076.     case NEXTHOP_TYPE_IPV6_IFINDEX:
  1077.     case NEXTHOP_TYPE_IPV6_IFNAME:
  1078.       vty_out (vty, " via %s)",
  1079.        inet_ntop (AF_INET6, &nexthop->rgate.ipv6,
  1080.   buf, BUFSIZ));
  1081.       if (nexthop->rifindex)
  1082. vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
  1083.       break;
  1084.     case NEXTHOP_TYPE_IFINDEX:
  1085.     case NEXTHOP_TYPE_IFNAME:
  1086.       vty_out (vty, " is directly connected, %s)",
  1087.        ifindex2ifname (nexthop->rifindex));
  1088.       break;
  1089.     default:
  1090.       break;
  1091.     }
  1092. }
  1093.       if (rib->type == ZEBRA_ROUTE_RIPNG
  1094.   || rib->type == ZEBRA_ROUTE_OSPF6
  1095.   || rib->type == ZEBRA_ROUTE_BGP)
  1096. {
  1097.   time_t uptime;
  1098.   struct tm *tm;
  1099.   uptime = time (NULL);
  1100.   uptime -= rib->uptime;
  1101.   tm = gmtime (&uptime);
  1102. #define ONE_DAY_SECOND 60*60*24
  1103. #define ONE_WEEK_SECOND 60*60*24*7
  1104.   if (uptime < ONE_DAY_SECOND)
  1105.     vty_out (vty,  ", %02d:%02d:%02d", 
  1106.      tm->tm_hour, tm->tm_min, tm->tm_sec);
  1107.   else if (uptime < ONE_WEEK_SECOND)
  1108.     vty_out (vty, ", %dd%02dh%02dm", 
  1109.      tm->tm_yday, tm->tm_hour, tm->tm_min);
  1110.   else
  1111.     vty_out (vty, ", %02dw%dd%02dh", 
  1112.      tm->tm_yday/7,
  1113.      tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
  1114. }
  1115.       vty_out (vty, "%s", VTY_NEWLINE);
  1116.     }
  1117. }
  1118. #define SHOW_ROUTE_V6_HEADER "Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3,%s       B - BGP, * - FIB route.%s%s"
  1119. DEFUN (show_ipv6_route,
  1120.        show_ipv6_route_cmd,
  1121.        "show ipv6 route",
  1122.        SHOW_STR
  1123.        IP_STR
  1124.        "IPv6 routing tablen")
  1125. {
  1126.   struct route_table *table;
  1127.   struct route_node *rn;
  1128.   struct rib *rib;
  1129.   int first = 1;
  1130.   table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
  1131.   if (! table)
  1132.     return CMD_SUCCESS;
  1133.   /* Show all IPv6 route. */
  1134.   for (rn = route_top (table); rn; rn = route_next (rn))
  1135.     for (rib = rn->info; rib; rib = rib->next)
  1136.       {
  1137. if (first)
  1138.   {
  1139.     vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
  1140.     first = 0;
  1141.   }
  1142. vty_show_ipv6_route (vty, rn, rib);
  1143.       }
  1144.   return CMD_SUCCESS;
  1145. }
  1146. DEFUN (show_ipv6_route_prefix_longer,
  1147.        show_ipv6_route_prefix_longer_cmd,
  1148.        "show ipv6 route X:X::X:X/M longer-prefixes",
  1149.        SHOW_STR
  1150.        IP_STR
  1151.        "IPv6 routing tablen"
  1152.        "IPv6 prefixn"
  1153.        "Show route matching the specified Network/Mask pair onlyn")
  1154. {
  1155.   struct route_table *table;
  1156.   struct route_node *rn;
  1157.   struct rib *rib;
  1158.   struct prefix p;
  1159.   int ret;
  1160.   int first = 1;
  1161.   table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
  1162.   if (! table)
  1163.     return CMD_SUCCESS;
  1164.   ret = str2prefix (argv[0], &p);
  1165.   if (! ret)
  1166.     {
  1167.       vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
  1168.       return CMD_WARNING;
  1169.     }
  1170.   /* Show matched type IPv6 routes. */
  1171.   for (rn = route_top (table); rn; rn = route_next (rn))
  1172.     for (rib = rn->info; rib; rib = rib->next)
  1173.       if (prefix_match (&p, &rn->p))
  1174. {
  1175.   if (first)
  1176.     {
  1177.       vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
  1178.       first = 0;
  1179.     }
  1180.   vty_show_ipv6_route (vty, rn, rib);
  1181. }
  1182.   return CMD_SUCCESS;
  1183. }
  1184. DEFUN (show_ipv6_route_protocol,
  1185.        show_ipv6_route_protocol_cmd,
  1186.        "show ipv6 route (bgp|connected|kernel|ospf6|ripng|static)",
  1187.        SHOW_STR
  1188.        IP_STR
  1189.        "IP routing tablen"
  1190.        "Border Gateway Protocol (BGP)n"
  1191.        "Connectedn"
  1192.        "Kerneln"
  1193.        "Open Shortest Path First (OSPFv3)n"
  1194.        "Routing Information Protocol (RIPng)n"
  1195.        "Static routesn")
  1196. {
  1197.   int type;
  1198.   struct route_table *table;
  1199.   struct route_node *rn;
  1200.   struct rib *rib;
  1201.   int first = 1;
  1202.   if (strncmp (argv[0], "b", 1) == 0)
  1203.     type = ZEBRA_ROUTE_BGP;
  1204.   else if (strncmp (argv[0], "c", 1) == 0)
  1205.     type = ZEBRA_ROUTE_CONNECT;
  1206.   else if (strncmp (argv[0], "k", 1) ==0)
  1207.     type = ZEBRA_ROUTE_KERNEL;
  1208.   else if (strncmp (argv[0], "o", 1) == 0)
  1209.     type = ZEBRA_ROUTE_OSPF6;
  1210.   else if (strncmp (argv[0], "r", 1) == 0)
  1211.     type = ZEBRA_ROUTE_RIPNG;
  1212.   else if (strncmp (argv[0], "s", 1) == 0)
  1213.     type = ZEBRA_ROUTE_STATIC;
  1214.   else 
  1215.     {
  1216.       vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
  1217.       return CMD_WARNING;
  1218.     }
  1219.   
  1220.   table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
  1221.   if (! table)
  1222.     return CMD_SUCCESS;
  1223.   /* Show matched type IPv6 routes. */
  1224.   for (rn = route_top (table); rn; rn = route_next (rn))
  1225.     for (rib = rn->info; rib; rib = rib->next)
  1226.       if (rib->type == type)
  1227. {
  1228.   if (first)
  1229.     {
  1230.       vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
  1231.       first = 0;
  1232.     }
  1233.   vty_show_ipv6_route (vty, rn, rib);
  1234. }
  1235.   return CMD_SUCCESS;
  1236. }
  1237. DEFUN (show_ipv6_route_addr,
  1238.        show_ipv6_route_addr_cmd,
  1239.        "show ipv6 route X:X::X:X",
  1240.        SHOW_STR
  1241.        IP_STR
  1242.        "IPv6 routing tablen"
  1243.        "IPv6 Addressn")
  1244. {
  1245.   int ret;
  1246.   struct prefix_ipv6 p;
  1247.   struct route_table *table;
  1248.   struct route_node *rn;
  1249.   ret = str2prefix_ipv6 (argv[0], &p);
  1250.   if (ret <= 0)
  1251.     {
  1252.       vty_out (vty, "Malformed IPv6 address%s", VTY_NEWLINE);
  1253.       return CMD_WARNING;
  1254.     }
  1255.   table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
  1256.   if (! table)
  1257.     return CMD_SUCCESS;
  1258.   rn = route_node_match (table, (struct prefix *) &p);
  1259.   if (! rn)
  1260.     {
  1261.       vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
  1262.       return CMD_WARNING;
  1263.     }
  1264.   vty_show_ipv6_route_detail (vty, rn);
  1265.   route_unlock_node (rn);
  1266.   return CMD_SUCCESS;
  1267. }
  1268. DEFUN (show_ipv6_route_prefix,
  1269.        show_ipv6_route_prefix_cmd,
  1270.        "show ipv6 route X:X::X:X/M",
  1271.        SHOW_STR
  1272.        IP_STR
  1273.        "IPv6 routing tablen"
  1274.        "IPv6 prefixn")
  1275. {
  1276.   int ret;
  1277.   struct prefix_ipv6 p;
  1278.   struct route_table *table;
  1279.   struct route_node *rn;
  1280.   ret = str2prefix_ipv6 (argv[0], &p);
  1281.   if (ret <= 0)
  1282.     {
  1283.       vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
  1284.       return CMD_WARNING;
  1285.     }
  1286.   table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
  1287.   if (! table)
  1288.     return CMD_SUCCESS;
  1289.   rn = route_node_match (table, (struct prefix *) &p);
  1290.   if (! rn || rn->p.prefixlen != p.prefixlen)
  1291.     {
  1292.       vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
  1293.       return CMD_WARNING;
  1294.     }
  1295.   vty_show_ipv6_route_detail (vty, rn);
  1296.   route_unlock_node (rn);
  1297.   return CMD_SUCCESS;
  1298. }
  1299. /* Write IPv6 static route configuration. */
  1300. int
  1301. static_config_ipv6 (struct vty *vty)
  1302. {
  1303.   struct route_node *rn;
  1304.   struct static_ipv6 *si;  
  1305.   int write;
  1306.   char buf[BUFSIZ];
  1307.   struct route_table *stable;
  1308.   write = 0;
  1309.   /* Lookup table.  */
  1310.   stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, 0);
  1311.   if (! stable)
  1312.     return -1;
  1313.   for (rn = route_top (stable); rn; rn = route_next (rn))
  1314.     for (si = rn->info; si; si = si->next)
  1315.       {
  1316. vty_out (vty, "ipv6 route %s/%d",
  1317.  inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
  1318.  rn->p.prefixlen);
  1319. switch (si->type)
  1320.   {
  1321.   case STATIC_IPV6_GATEWAY:
  1322.     vty_out (vty, " %s", inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ));
  1323.     break;
  1324.   case STATIC_IPV6_IFNAME:
  1325.     vty_out (vty, " %s", si->ifname);
  1326.     break;
  1327.   case STATIC_IPV6_GATEWAY_IFNAME:
  1328.     vty_out (vty, " %s %s",
  1329.      inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ), si->ifname);
  1330.     break;
  1331.   case STATIC_IPV6_BLACKHOLE:
  1332.     vty_out (vty, " Null0");
  1333.     break;
  1334.   }
  1335. if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
  1336.   vty_out (vty, " %d", si->distance);
  1337. vty_out (vty, "%s", VTY_NEWLINE);
  1338. write = 1;
  1339.       }
  1340.   return write;
  1341. }
  1342. #endif /* HAVE_IPV6 */
  1343. /* Static ip route configuration write function. */
  1344. int
  1345. zebra_ip_config (struct vty *vty)
  1346. {
  1347.   int write = 0;
  1348.   write += static_config_ipv4 (vty);
  1349. #ifdef HAVE_IPV6
  1350.   write += static_config_ipv6 (vty);
  1351. #endif /* HAVE_IPV6 */
  1352.   return write;
  1353. }
  1354. /* IP node for static routes. */
  1355. struct cmd_node ip_node = { IP_NODE,  "",  1 };
  1356. /* Route VTY.  */
  1357. void
  1358. zebra_vty_route_init ()
  1359. {
  1360.   install_node (&ip_node, zebra_ip_config);
  1361.   install_element (CONFIG_NODE, &ip_route_cmd);
  1362.   install_element (CONFIG_NODE, &ip_route_mask_cmd);
  1363.   install_element (CONFIG_NODE, &no_ip_route_cmd);
  1364.   install_element (CONFIG_NODE, &no_ip_route_mask_cmd);
  1365.   install_element (CONFIG_NODE, &ip_route_distance_cmd);
  1366.   install_element (CONFIG_NODE, &ip_route_mask_distance_cmd);
  1367.   install_element (CONFIG_NODE, &no_ip_route_distance_cmd);
  1368.   install_element (CONFIG_NODE, &no_ip_route_mask_distance_cmd);
  1369.   install_element (VIEW_NODE, &show_ip_route_cmd);
  1370.   install_element (VIEW_NODE, &show_ip_route_addr_cmd);
  1371.   install_element (VIEW_NODE, &show_ip_route_prefix_cmd);
  1372.   install_element (VIEW_NODE, &show_ip_route_prefix_longer_cmd);
  1373.   install_element (VIEW_NODE, &show_ip_route_protocol_cmd);
  1374.   install_element (VIEW_NODE, &show_ip_route_supernets_cmd);
  1375.   install_element (ENABLE_NODE, &show_ip_route_cmd);
  1376.   install_element (ENABLE_NODE, &show_ip_route_addr_cmd);
  1377.   install_element (ENABLE_NODE, &show_ip_route_prefix_cmd);
  1378.   install_element (ENABLE_NODE, &show_ip_route_prefix_longer_cmd);
  1379.   install_element (ENABLE_NODE, &show_ip_route_protocol_cmd);
  1380.   install_element (ENABLE_NODE, &show_ip_route_supernets_cmd);
  1381. #if 0
  1382.   install_element (VIEW_NODE, &show_ip_route_summary_cmd);
  1383.   install_element (ENABLE_NODE, &show_ip_route_summary_cmd);
  1384. #endif /* 0 */
  1385. #ifdef HAVE_IPV6
  1386.   install_element (CONFIG_NODE, &ipv6_route_cmd);
  1387.   install_element (CONFIG_NODE, &ipv6_route_ifname_cmd);
  1388.   install_element (CONFIG_NODE, &no_ipv6_route_cmd);
  1389.   install_element (CONFIG_NODE, &no_ipv6_route_ifname_cmd);
  1390.   install_element (CONFIG_NODE, &ipv6_route_pref_cmd);
  1391.   install_element (CONFIG_NODE, &ipv6_route_ifname_pref_cmd);
  1392.   install_element (CONFIG_NODE, &no_ipv6_route_pref_cmd);
  1393.   install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_cmd);
  1394.   install_element (VIEW_NODE, &show_ipv6_route_cmd);
  1395.   install_element (VIEW_NODE, &show_ipv6_route_protocol_cmd);
  1396.   install_element (VIEW_NODE, &show_ipv6_route_addr_cmd);
  1397.   install_element (VIEW_NODE, &show_ipv6_route_prefix_cmd);
  1398.   install_element (VIEW_NODE, &show_ipv6_route_prefix_longer_cmd);
  1399.   install_element (ENABLE_NODE, &show_ipv6_route_cmd);
  1400.   install_element (ENABLE_NODE, &show_ipv6_route_protocol_cmd);
  1401.   install_element (ENABLE_NODE, &show_ipv6_route_addr_cmd);
  1402.   install_element (ENABLE_NODE, &show_ipv6_route_prefix_cmd);
  1403.   install_element (ENABLE_NODE, &show_ipv6_route_prefix_longer_cmd);
  1404. #endif /* HAVE_IPV6 */
  1405. }
  1406. void
  1407. zebra_vty_init ()
  1408. {
  1409.   zebra_vty_route_init ();
  1410. }