| /* Zebra VTY functions |
| * Copyright (C) 2002 Kunihiro Ishiguro |
| * |
| * This file is part of GNU Zebra. |
| * |
| * GNU Zebra is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License as published by the |
| * Free Software Foundation; either version 2, or (at your option) any |
| * later version. |
| * |
| * GNU Zebra is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with GNU Zebra; see the file COPYING. If not, write to the |
| * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| * Boston, MA 02111-1307, USA. |
| */ |
| |
| #include <zebra.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"; |
| } |
| }; |
| |
| /* 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 '?'; |
| } |
| }; |
| |
| /* General fucntion for static route. */ |
| 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) |
| { |
| int ret; |
| u_char distance; |
| struct prefix p; |
| struct in_addr gate; |
| struct in_addr mask; |
| const char *ifname; |
| u_char flag = 0; |
| |
| ret = str2prefix (dest_str, &p); |
| if (ret <= 0) |
| { |
| vty_out (vty, "%% Malformed address%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| /* Cisco like mask notation. */ |
| if (mask_str) |
| { |
| ret = inet_aton (mask_str, &mask); |
| if (ret == 0) |
| { |
| vty_out (vty, "%% Malformed address%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| p.prefixlen = ip_masklen (mask); |
| } |
| |
| /* Apply mask for given prefix. */ |
| apply_mask (&p); |
| |
| /* Administrative distance. */ |
| if (distance_str) |
| distance = atoi (distance_str); |
| else |
| distance = ZEBRA_STATIC_DISTANCE_DEFAULT; |
| |
| /* Null0 static route. */ |
| if ((gate_str != NULL) && (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)) |
| { |
| if (flag_str) |
| { |
| vty_out (vty, "%% can not have flag %s with Null0%s", flag_str, VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| if (add_cmd) |
| static_add_ipv4 (&p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE, distance, 0); |
| else |
| static_delete_ipv4 (&p, NULL, NULL, distance, 0); |
| return CMD_SUCCESS; |
| } |
| |
| /* Route flags */ |
| if (flag_str) { |
| switch(flag_str[0]) { |
| case 'r': |
| case 'R': /* XXX */ |
| SET_FLAG (flag, ZEBRA_FLAG_REJECT); |
| break; |
| case 'b': |
| case 'B': /* XXX */ |
| SET_FLAG (flag, ZEBRA_FLAG_BLACKHOLE); |
| break; |
| default: |
| vty_out (vty, "%% Malformed flag %s %s", flag_str, VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| } |
| |
| if (gate_str == NULL) |
| { |
| if (add_cmd) |
| static_add_ipv4 (&p, NULL, NULL, flag, distance, 0); |
| else |
| static_delete_ipv4 (&p, NULL, NULL, distance, 0); |
| |
| return CMD_SUCCESS; |
| } |
| |
| /* When gateway is A.B.C.D format, gate is treated as nexthop |
| address other case gate is treated as interface name. */ |
| ret = inet_aton (gate_str, &gate); |
| if (ret) |
| ifname = NULL; |
| else |
| ifname = gate_str; |
| |
| if (add_cmd) |
| static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, distance, 0); |
| else |
| static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, distance, 0); |
| |
| return CMD_SUCCESS; |
| } |
| |
| /* Static route configuration. */ |
| DEFUN (ip_route, |
| ip_route_cmd, |
| "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0)", |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix (e.g. 10.0.0.0/8)\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Null interface\n") |
| { |
| return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL); |
| } |
| |
| DEFUN (ip_route_flags, |
| ip_route_flags_cmd, |
| "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole)", |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix (e.g. 10.0.0.0/8)\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n") |
| { |
| return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL); |
| } |
| |
| DEFUN (ip_route_flags2, |
| ip_route_flags2_cmd, |
| "ip route A.B.C.D/M (reject|blackhole)", |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix (e.g. 10.0.0.0/8)\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n") |
| { |
| return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL); |
| } |
| |
| /* Mask as A.B.C.D format. */ |
| DEFUN (ip_route_mask, |
| ip_route_mask_cmd, |
| "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0)", |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix\n" |
| "IP destination prefix mask\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Null interface\n") |
| { |
| return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL); |
| } |
| |
| DEFUN (ip_route_mask_flags, |
| ip_route_mask_flags_cmd, |
| "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole)", |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix\n" |
| "IP destination prefix mask\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n") |
| { |
| return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL); |
| } |
| |
| DEFUN (ip_route_mask_flags2, |
| ip_route_mask_flags2_cmd, |
| "ip route A.B.C.D A.B.C.D (reject|blackhole)", |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix\n" |
| "IP destination prefix mask\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n") |
| { |
| return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL); |
| } |
| |
| /* Distance option value. */ |
| DEFUN (ip_route_distance, |
| ip_route_distance_cmd, |
| "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>", |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix (e.g. 10.0.0.0/8)\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Null interface\n" |
| "Distance value for this route\n") |
| { |
| return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2]); |
| } |
| |
| DEFUN (ip_route_flags_distance, |
| ip_route_flags_distance_cmd, |
| "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>", |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix (e.g. 10.0.0.0/8)\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n" |
| "Distance value for this route\n") |
| { |
| return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3]); |
| } |
| |
| DEFUN (ip_route_flags_distance2, |
| ip_route_flags_distance2_cmd, |
| "ip route A.B.C.D/M (reject|blackhole) <1-255>", |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix (e.g. 10.0.0.0/8)\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n" |
| "Distance value for this route\n") |
| { |
| return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2]); |
| } |
| |
| DEFUN (ip_route_mask_distance, |
| ip_route_mask_distance_cmd, |
| "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) <1-255>", |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix\n" |
| "IP destination prefix mask\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Null interface\n" |
| "Distance value for this route\n") |
| { |
| return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3]); |
| } |
| |
| DEFUN (ip_route_mask_flags_distance, |
| ip_route_mask_flags_distance_cmd, |
| "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>", |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix\n" |
| "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") |
| { |
| return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4]); |
| } |
| |
| DEFUN (ip_route_mask_flags_distance2, |
| ip_route_mask_flags_distance2_cmd, |
| "ip route A.B.C.D A.B.C.D (reject|blackhole) <1-255>", |
| IP_STR |
| "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") |
| { |
| return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3]); |
| } |
| |
| DEFUN (no_ip_route, |
| no_ip_route_cmd, |
| "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0)", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix (e.g. 10.0.0.0/8)\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Null interface\n") |
| { |
| return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL); |
| } |
| |
| ALIAS (no_ip_route, |
| no_ip_route_flags_cmd, |
| "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole)", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix (e.g. 10.0.0.0/8)\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n") |
| |
| DEFUN (no_ip_route_flags2, |
| no_ip_route_flags2_cmd, |
| "no ip route A.B.C.D/M (reject|blackhole)", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix (e.g. 10.0.0.0/8)\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n") |
| { |
| return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, NULL); |
| } |
| |
| DEFUN (no_ip_route_mask, |
| no_ip_route_mask_cmd, |
| "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0)", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix\n" |
| "IP destination prefix mask\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Null interface\n") |
| { |
| return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL); |
| } |
| |
| ALIAS (no_ip_route_mask, |
| no_ip_route_mask_flags_cmd, |
| "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole)", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix\n" |
| "IP destination prefix mask\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n") |
| |
| DEFUN (no_ip_route_mask_flags2, |
| no_ip_route_mask_flags2_cmd, |
| "no ip route A.B.C.D A.B.C.D (reject|blackhole)", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix\n" |
| "IP destination prefix mask\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n") |
| { |
| return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, NULL); |
| } |
| |
| DEFUN (no_ip_route_distance, |
| no_ip_route_distance_cmd, |
| "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix (e.g. 10.0.0.0/8)\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Null interface\n" |
| "Distance value for this route\n") |
| { |
| return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2]); |
| } |
| |
| DEFUN (no_ip_route_flags_distance, |
| no_ip_route_flags_distance_cmd, |
| "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix (e.g. 10.0.0.0/8)\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n" |
| "Distance value for this route\n") |
| { |
| return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], argv[3]); |
| } |
| |
| DEFUN (no_ip_route_flags_distance2, |
| no_ip_route_flags_distance2_cmd, |
| "no ip route A.B.C.D/M (reject|blackhole) <1-255>", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix (e.g. 10.0.0.0/8)\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n" |
| "Distance value for this route\n") |
| { |
| return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], argv[2]); |
| } |
| |
| DEFUN (no_ip_route_mask_distance, |
| no_ip_route_mask_distance_cmd, |
| "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) <1-255>", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix\n" |
| "IP destination prefix mask\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Null interface\n" |
| "Distance value for this route\n") |
| { |
| return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3]); |
| } |
| |
| DEFUN (no_ip_route_mask_flags_distance, |
| no_ip_route_mask_flags_distance_cmd, |
| "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix\n" |
| "IP destination prefix mask\n" |
| "IP gateway address\n" |
| "IP gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n" |
| "Distance value for this route\n") |
| { |
| return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4]); |
| } |
| |
| DEFUN (no_ip_route_mask_flags_distance2, |
| no_ip_route_mask_flags_distance2_cmd, |
| "no ip route A.B.C.D A.B.C.D (reject|blackhole) <1-255>", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IP destination prefix\n" |
| "IP destination prefix mask\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n" |
| "Distance value for this route\n") |
| { |
| return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3]); |
| } |
| |
| /* New RIB. Detailed information for IPv4 route. */ |
| void |
| vty_show_ip_route_detail (struct vty *vty, struct route_node *rn) |
| { |
| struct rib *rib; |
| struct nexthop *nexthop; |
| |
| for (rib = rn->info; rib; rib = rib->next) |
| { |
| 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); |
| if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) |
| vty_out (vty, ", best"); |
| if (rib->refcnt) |
| vty_out (vty, ", refcnt %ld", rib->refcnt); |
| if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) |
| vty_out (vty, ", blackhole"); |
| if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT)) |
| vty_out (vty, ", reject"); |
| vty_out (vty, "%s", VTY_NEWLINE); |
| |
| #define ONE_DAY_SECOND 60*60*24 |
| #define ONE_WEEK_SECOND 60*60*24*7 |
| if (rib->type == ZEBRA_ROUTE_RIP |
| || rib->type == ZEBRA_ROUTE_OSPF |
| || rib->type == ZEBRA_ROUTE_ISIS |
| || rib->type == ZEBRA_ROUTE_BGP) |
| { |
| time_t uptime; |
| struct tm *tm; |
| |
| uptime = time (NULL); |
| uptime -= rib->uptime; |
| tm = gmtime (&uptime); |
| |
| vty_out (vty, " Last update "); |
| |
| if (uptime < ONE_DAY_SECOND) |
| vty_out (vty, "%02d:%02d:%02d", |
| tm->tm_hour, tm->tm_min, tm->tm_sec); |
| else if (uptime < ONE_WEEK_SECOND) |
| vty_out (vty, "%dd%02dh%02dm", |
| tm->tm_yday, tm->tm_hour, tm->tm_min); |
| else |
| vty_out (vty, "%02dw%dd%02dh", |
| tm->tm_yday/7, |
| tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); |
| vty_out (vty, " ago%s", VTY_NEWLINE); |
| } |
| |
| for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) |
| { |
| vty_out (vty, " %c", |
| CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' '); |
| |
| switch (nexthop->type) |
| { |
| case NEXTHOP_TYPE_IPV4: |
| case NEXTHOP_TYPE_IPV4_IFINDEX: |
| vty_out (vty, " %s", inet_ntoa (nexthop->gate.ipv4)); |
| if (nexthop->ifindex) |
| vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex)); |
| break; |
| case NEXTHOP_TYPE_IFINDEX: |
| vty_out (vty, " directly connected, %s", |
| ifindex2ifname (nexthop->ifindex)); |
| break; |
| case NEXTHOP_TYPE_IFNAME: |
| vty_out (vty, " directly connected, %s", nexthop->ifname); |
| break; |
| case NEXTHOP_TYPE_BLACKHOLE: |
| vty_out (vty, " directly connected, Null0"); |
| break; |
| default: |
| break; |
| } |
| if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) |
| vty_out (vty, " inactive"); |
| |
| 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, "%s", VTY_NEWLINE); |
| } |
| vty_out (vty, "%s", VTY_NEWLINE); |
| } |
| } |
| |
| void |
| vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) |
| { |
| struct nexthop *nexthop; |
| int len = 0; |
| char buf[BUFSIZ]; |
| |
| /* Nexthop information. */ |
| for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) |
| { |
| if (nexthop == rib->nexthop) |
| { |
| /* Prefix information. */ |
| len = vty_out (vty, "%c%c%c %s/%d", |
| route_type_char (rib->type), |
| CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) |
| ? '>' : ' ', |
| CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) |
| ? '*' : ' ', |
| inet_ntop (AF_INET, &rn->p.u.prefix, buf, BUFSIZ), |
| rn->p.prefixlen); |
| |
| /* Distance and metric display. */ |
| if (rib->type != ZEBRA_ROUTE_CONNECT |
| && rib->type != ZEBRA_ROUTE_KERNEL) |
| len += vty_out (vty, " [%d/%d]", rib->distance, |
| rib->metric); |
| } |
| else |
| vty_out (vty, " %c%*c", |
| CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) |
| ? '*' : ' ', |
| len - 3, ' '); |
| |
| switch (nexthop->type) |
| { |
| case NEXTHOP_TYPE_IPV4: |
| case NEXTHOP_TYPE_IPV4_IFINDEX: |
| vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); |
| if (nexthop->ifindex) |
| vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex)); |
| break; |
| case NEXTHOP_TYPE_IFINDEX: |
| vty_out (vty, " is directly connected, %s", |
| ifindex2ifname (nexthop->ifindex)); |
| break; |
| case NEXTHOP_TYPE_IFNAME: |
| vty_out (vty, " is directly connected, %s", nexthop->ifname); |
| break; |
| case NEXTHOP_TYPE_BLACKHOLE: |
| vty_out (vty, " is directly connected, Null0"); |
| break; |
| default: |
| break; |
| } |
| if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) |
| vty_out (vty, " inactive"); |
| |
| 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; |
| } |
| } |
| |
| if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) |
| vty_out (vty, ", bh"); |
| if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT)) |
| vty_out (vty, ", rej"); |
| |
| if (rib->type == ZEBRA_ROUTE_RIP |
| || rib->type == ZEBRA_ROUTE_OSPF |
| || rib->type == ZEBRA_ROUTE_ISIS |
| || rib->type == ZEBRA_ROUTE_BGP) |
| { |
| time_t uptime; |
| struct tm *tm; |
| |
| uptime = time (NULL); |
| uptime -= rib->uptime; |
| tm = gmtime (&uptime); |
| |
| #define ONE_DAY_SECOND 60*60*24 |
| #define ONE_WEEK_SECOND 60*60*24*7 |
| |
| if (uptime < ONE_DAY_SECOND) |
| vty_out (vty, ", %02d:%02d:%02d", |
| tm->tm_hour, tm->tm_min, tm->tm_sec); |
| else if (uptime < ONE_WEEK_SECOND) |
| vty_out (vty, ", %dd%02dh%02dm", |
| tm->tm_yday, tm->tm_hour, tm->tm_min); |
| else |
| vty_out (vty, ", %02dw%dd%02dh", |
| tm->tm_yday/7, |
| tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); |
| } |
| vty_out (vty, "%s", VTY_NEWLINE); |
| } |
| } |
| |
| #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", |
| SHOW_STR |
| IP_STR |
| "IP routing table\n") |
| { |
| struct route_table *table; |
| struct route_node *rn; |
| struct rib *rib; |
| int first = 1; |
| |
| table = vrf_table (AFI_IP, SAFI_UNICAST, 0); |
| if (! table) |
| return CMD_SUCCESS; |
| |
| /* Show all IPv4 routes. */ |
| for (rn = route_top (table); rn; rn = route_next (rn)) |
| for (rib = rn->info; rib; rib = rib->next) |
| { |
| if (first) |
| { |
| vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE, |
| VTY_NEWLINE); |
| first = 0; |
| } |
| vty_show_ip_route (vty, rn, rib); |
| } |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (show_ip_route_prefix_longer, |
| show_ip_route_prefix_longer_cmd, |
| "show ip route A.B.C.D/M longer-prefixes", |
| SHOW_STR |
| IP_STR |
| "IP routing table\n" |
| "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" |
| "Show route matching the specified Network/Mask pair only\n") |
| { |
| struct route_table *table; |
| struct route_node *rn; |
| struct rib *rib; |
| struct prefix p; |
| int ret; |
| int first = 1; |
| |
| ret = str2prefix (argv[0], &p); |
| if (! ret) |
| { |
| vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| table = vrf_table (AFI_IP, SAFI_UNICAST, 0); |
| if (! table) |
| return CMD_SUCCESS; |
| |
| /* Show matched type IPv4 routes. */ |
| for (rn = route_top (table); rn; rn = route_next (rn)) |
| for (rib = rn->info; rib; rib = rib->next) |
| if (prefix_match (&p, &rn->p)) |
| { |
| if (first) |
| { |
| vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, |
| VTY_NEWLINE, VTY_NEWLINE); |
| first = 0; |
| } |
| vty_show_ip_route (vty, rn, rib); |
| } |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (show_ip_route_supernets, |
| show_ip_route_supernets_cmd, |
| "show ip route supernets-only", |
| SHOW_STR |
| IP_STR |
| "IP routing table\n" |
| "Show supernet entries only\n") |
| { |
| struct route_table *table; |
| struct route_node *rn; |
| struct rib *rib; |
| u_int32_t addr; |
| int first = 1; |
| |
| table = vrf_table (AFI_IP, SAFI_UNICAST, 0); |
| if (! table) |
| return CMD_SUCCESS; |
| |
| /* Show matched type IPv4 routes. */ |
| for (rn = route_top (table); rn; rn = route_next (rn)) |
| for (rib = rn->info; rib; rib = rib->next) |
| { |
| addr = ntohl (rn->p.u.prefix4.s_addr); |
| |
| if ((IN_CLASSC (addr) && rn->p.prefixlen < 24) |
| || (IN_CLASSB (addr) && rn->p.prefixlen < 16) |
| || (IN_CLASSA (addr) && rn->p.prefixlen < 8)) |
| { |
| if (first) |
| { |
| vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, |
| VTY_NEWLINE, VTY_NEWLINE); |
| first = 0; |
| } |
| vty_show_ip_route (vty, rn, rib); |
| } |
| } |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (show_ip_route_protocol, |
| show_ip_route_protocol_cmd, |
| "show ip route (bgp|connected|isis|kernel|ospf|rip|static)", |
| 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") |
| { |
| int type; |
| struct route_table *table; |
| struct route_node *rn; |
| 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 |
| { |
| vty_out (vty, "Unknown route type%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| table = vrf_table (AFI_IP, SAFI_UNICAST, 0); |
| if (! table) |
| return CMD_SUCCESS; |
| |
| /* Show matched type IPv4 routes. */ |
| for (rn = route_top (table); rn; rn = route_next (rn)) |
| for (rib = rn->info; rib; rib = rib->next) |
| if (rib->type == type) |
| { |
| if (first) |
| { |
| vty_out (vty, SHOW_ROUTE_V4_HEADER, |
| VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); |
| first = 0; |
| } |
| vty_show_ip_route (vty, rn, rib); |
| } |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (show_ip_route_addr, |
| show_ip_route_addr_cmd, |
| "show ip route A.B.C.D", |
| SHOW_STR |
| IP_STR |
| "IP routing table\n" |
| "Network in the IP routing table to display\n") |
| { |
| int ret; |
| struct prefix_ipv4 p; |
| struct route_table *table; |
| struct route_node *rn; |
| |
| ret = str2prefix_ipv4 (argv[0], &p); |
| if (ret <= 0) |
| { |
| vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| table = vrf_table (AFI_IP, SAFI_UNICAST, 0); |
| if (! table) |
| return CMD_SUCCESS; |
| |
| rn = route_node_match (table, (struct prefix *) &p); |
| if (! rn) |
| { |
| vty_out (vty, "%% Network not in table%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| vty_show_ip_route_detail (vty, rn); |
| |
| route_unlock_node (rn); |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (show_ip_route_prefix, |
| show_ip_route_prefix_cmd, |
| "show ip route A.B.C.D/M", |
| SHOW_STR |
| IP_STR |
| "IP routing table\n" |
| "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") |
| { |
| int ret; |
| struct prefix_ipv4 p; |
| struct route_table *table; |
| struct route_node *rn; |
| |
| ret = str2prefix_ipv4 (argv[0], &p); |
| if (ret <= 0) |
| { |
| vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| table = vrf_table (AFI_IP, SAFI_UNICAST, 0); |
| if (! table) |
| return CMD_SUCCESS; |
| |
| rn = route_node_match (table, (struct prefix *) &p); |
| if (! rn || rn->p.prefixlen != p.prefixlen) |
| { |
| vty_out (vty, "%% Network not in table%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| vty_show_ip_route_detail (vty, rn); |
| |
| route_unlock_node (rn); |
| |
| return CMD_SUCCESS; |
| } |
| |
| void |
| zebra_show_ip_route (struct vty *vty, struct vrf *vrf) |
| { |
| 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); |
| |
| 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, "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); |
| |
| vty_out (vty, "internal %d%s", 0, VTY_NEWLINE); |
| vty_out (vty, "Total %d%s", 0, VTY_NEWLINE); |
| } |
| |
| /* Show route summary. */ |
| DEFUN (show_ip_route_summary, |
| show_ip_route_summary_cmd, |
| "show ip route summary", |
| SHOW_STR |
| IP_STR |
| "IP routing table\n" |
| "Summary of all routes\n") |
| { |
| struct vrf *vrf; |
| |
| /* 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; |
| } |
| |
| zebra_show_ip_route (vty, vrf); |
| |
| return CMD_SUCCESS; |
| } |
| |
| /* Write IPv4 static route configuration. */ |
| int |
| static_config_ipv4 (struct vty *vty) |
| { |
| struct route_node *rn; |
| struct static_ipv4 *si; |
| struct route_table *stable; |
| int write; |
| |
| write = 0; |
| |
| /* Lookup table. */ |
| stable = vrf_static_table (AFI_IP, SAFI_UNICAST, 0); |
| if (! stable) |
| return -1; |
| |
| for (rn = route_top (stable); rn; rn = route_next (rn)) |
| for (si = rn->info; si; si = si->next) |
| { |
| vty_out (vty, "ip route %s/%d", inet_ntoa (rn->p.u.prefix4), |
| rn->p.prefixlen); |
| |
| switch (si->type) |
| { |
| case STATIC_IPV4_GATEWAY: |
| vty_out (vty, " %s", inet_ntoa (si->gate.ipv4)); |
| break; |
| case STATIC_IPV4_IFNAME: |
| vty_out (vty, " %s", si->gate.ifname); |
| break; |
| case STATIC_IPV4_BLACKHOLE: |
| vty_out (vty, " Null0"); |
| break; |
| } |
| |
| /* flags are incompatible with STATIC_IPV4_BLACKHOLE */ |
| if (si->type != STATIC_IPV4_BLACKHOLE) |
| { |
| if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT)) |
| vty_out (vty, " %s", "reject"); |
| |
| if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) |
| vty_out (vty, " %s", "blackhole"); |
| } |
| |
| if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) |
| vty_out (vty, " %d", si->distance); |
| |
| vty_out (vty, "%s", VTY_NEWLINE); |
| |
| write = 1; |
| } |
| return write; |
| } |
| |
| #ifdef HAVE_IPV6 |
| /* General fucntion for IPv6 static route. */ |
| 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) |
| { |
| int ret; |
| u_char distance; |
| struct prefix p; |
| struct in6_addr *gate = NULL; |
| struct in6_addr gate_addr; |
| u_char type = 0; |
| int table = 0; |
| u_char flag = 0; |
| |
| ret = str2prefix (dest_str, &p); |
| if (ret <= 0) |
| { |
| vty_out (vty, "%% Malformed address%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| /* Apply mask for given prefix. */ |
| apply_mask (&p); |
| |
| /* Route flags */ |
| if (flag_str) { |
| switch(flag_str[0]) { |
| case 'r': |
| case 'R': /* XXX */ |
| SET_FLAG (flag, ZEBRA_FLAG_REJECT); |
| break; |
| case 'b': |
| case 'B': /* XXX */ |
| SET_FLAG (flag, ZEBRA_FLAG_BLACKHOLE); |
| break; |
| default: |
| vty_out (vty, "%% Malformed flag %s %s", flag_str, VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| } |
| |
| /* Administrative distance. */ |
| if (distance_str) |
| distance = atoi (distance_str); |
| else |
| distance = ZEBRA_STATIC_DISTANCE_DEFAULT; |
| |
| /* When gateway is valid IPv6 addrees, then gate is treated as |
| nexthop address other case gate is treated as interface name. */ |
| ret = inet_pton (AF_INET6, gate_str, &gate_addr); |
| |
| if (ifname) |
| { |
| /* When ifname is specified. It must be come with gateway |
| address. */ |
| if (ret != 1) |
| { |
| vty_out (vty, "%% Malformed address%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| type = STATIC_IPV6_GATEWAY_IFNAME; |
| gate = &gate_addr; |
| } |
| else |
| { |
| if (ret == 1) |
| { |
| type = STATIC_IPV6_GATEWAY; |
| gate = &gate_addr; |
| } |
| else |
| { |
| type = STATIC_IPV6_IFNAME; |
| ifname = gate_str; |
| } |
| } |
| |
| if (add_cmd) |
| static_add_ipv6 (&p, type, gate, ifname, flag, distance, table); |
| else |
| static_delete_ipv6 (&p, type, gate, ifname, distance, table); |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (ipv6_route, |
| ipv6_route_cmd, |
| "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)", |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n") |
| { |
| return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL); |
| } |
| |
| DEFUN (ipv6_route_flags, |
| ipv6_route_flags_cmd, |
| "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)", |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n") |
| { |
| return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL); |
| } |
| |
| DEFUN (ipv6_route_ifname, |
| ipv6_route_ifname_cmd, |
| "ipv6 route X:X::X:X/M X:X::X:X INTERFACE", |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n") |
| { |
| return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL); |
| } |
| |
| DEFUN (ipv6_route_ifname_flags, |
| ipv6_route_ifname_flags_cmd, |
| "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)", |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n") |
| { |
| return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL); |
| } |
| |
| DEFUN (ipv6_route_pref, |
| ipv6_route_pref_cmd, |
| "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>", |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n" |
| "Distance value for this prefix\n") |
| { |
| return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2]); |
| } |
| |
| DEFUN (ipv6_route_flags_pref, |
| ipv6_route_flags_pref_cmd, |
| "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>", |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n" |
| "Distance value for this prefix\n") |
| { |
| return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3]); |
| } |
| |
| DEFUN (ipv6_route_ifname_pref, |
| ipv6_route_ifname_pref_cmd, |
| "ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>", |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n" |
| "Distance value for this prefix\n") |
| { |
| return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3]); |
| } |
| |
| DEFUN (ipv6_route_ifname_flags_pref, |
| ipv6_route_ifname_flags_pref_cmd, |
| "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>", |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n" |
| "Distance value for this prefix\n") |
| { |
| return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4]); |
| } |
| |
| DEFUN (no_ipv6_route, |
| no_ipv6_route_cmd, |
| "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n") |
| { |
| return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL); |
| } |
| |
| ALIAS (no_ipv6_route, |
| no_ipv6_route_flags_cmd, |
| "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n") |
| |
| DEFUN (no_ipv6_route_ifname, |
| no_ipv6_route_ifname_cmd, |
| "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n") |
| { |
| return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL); |
| } |
| |
| ALIAS (no_ipv6_route_ifname, |
| no_ipv6_route_ifname_flags_cmd, |
| "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n") |
| |
| DEFUN (no_ipv6_route_pref, |
| no_ipv6_route_pref_cmd, |
| "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n" |
| "Distance value for this prefix\n") |
| { |
| return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2]); |
| } |
| |
| DEFUN (no_ipv6_route_flags_pref, |
| no_ipv6_route_flags_pref_cmd, |
| "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n" |
| "Distance value for this prefix\n") |
| { |
| /* We do not care about argv[2] */ |
| return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3]); |
| } |
| |
| DEFUN (no_ipv6_route_ifname_pref, |
| no_ipv6_route_ifname_pref_cmd, |
| "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n" |
| "Distance value for this prefix\n") |
| { |
| return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3]); |
| } |
| |
| DEFUN (no_ipv6_route_ifname_flags_pref, |
| no_ipv6_route_ifname_flags_pref_cmd, |
| "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>", |
| NO_STR |
| IP_STR |
| "Establish static routes\n" |
| "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" |
| "IPv6 gateway address\n" |
| "IPv6 gateway interface name\n" |
| "Emit an ICMP unreachable when matched\n" |
| "Silently discard pkts when matched\n" |
| "Distance value for this prefix\n") |
| { |
| return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4]); |
| } |
| |
| /* New RIB. Detailed information for IPv6 route. */ |
| void |
| vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn) |
| { |
| struct rib *rib; |
| struct nexthop *nexthop; |
| char buf[BUFSIZ]; |
| |
| for (rib = rn->info; rib; rib = rib->next) |
| { |
| 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); |
| if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) |
| vty_out (vty, ", best"); |
| if (rib->refcnt) |
| vty_out (vty, ", refcnt %ld", rib->refcnt); |
| if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) |
| vty_out (vty, ", blackhole"); |
| if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT)) |
| vty_out (vty, ", reject"); |
| vty_out (vty, "%s", VTY_NEWLINE); |
| |
| #define ONE_DAY_SECOND 60*60*24 |
| #define ONE_WEEK_SECOND 60*60*24*7 |
| if (rib->type == ZEBRA_ROUTE_RIPNG |
| || rib->type == ZEBRA_ROUTE_OSPF6 |
| || rib->type == ZEBRA_ROUTE_ISIS |
| || rib->type == ZEBRA_ROUTE_BGP) |
| { |
| time_t uptime; |
| struct tm *tm; |
| |
| uptime = time (NULL); |
| uptime -= rib->uptime; |
| tm = gmtime (&uptime); |
| |
| vty_out (vty, " Last update "); |
| |
| if (uptime < ONE_DAY_SECOND) |
| vty_out (vty, "%02d:%02d:%02d", |
| tm->tm_hour, tm->tm_min, tm->tm_sec); |
| else if (uptime < ONE_WEEK_SECOND) |
| vty_out (vty, "%dd%02dh%02dm", |
| tm->tm_yday, tm->tm_hour, tm->tm_min); |
| else |
| vty_out (vty, "%02dw%dd%02dh", |
| tm->tm_yday/7, |
| tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); |
| vty_out (vty, " ago%s", VTY_NEWLINE); |
| } |
| |
| for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) |
| { |
| vty_out (vty, " %c", |
| CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' '); |
| |
| switch (nexthop->type) |
| { |
| case NEXTHOP_TYPE_IPV6: |
| case NEXTHOP_TYPE_IPV6_IFINDEX: |
| case NEXTHOP_TYPE_IPV6_IFNAME: |
| vty_out (vty, " %s", |
| inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); |
| if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME) |
| vty_out (vty, ", %s", nexthop->ifname); |
| else if (nexthop->ifindex) |
| vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex)); |
| break; |
| case NEXTHOP_TYPE_IFINDEX: |
| vty_out (vty, " directly connected, %s", |
| ifindex2ifname (nexthop->ifindex)); |
| break; |
| case NEXTHOP_TYPE_IFNAME: |
| vty_out (vty, " directly connected, %s", |
| nexthop->ifname); |
| break; |
| default: |
| break; |
| } |
| if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) |
| 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, "%s", VTY_NEWLINE); |
| } |
| vty_out (vty, "%s", VTY_NEWLINE); |
| } |
| } |
| |
| void |
| vty_show_ipv6_route (struct vty *vty, struct route_node *rn, |
| struct rib *rib) |
| { |
| struct nexthop *nexthop; |
| int len = 0; |
| char buf[BUFSIZ]; |
| |
| /* Nexthop information. */ |
| for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) |
| { |
| if (nexthop == rib->nexthop) |
| { |
| /* Prefix information. */ |
| len = vty_out (vty, "%c%c%c %s/%d", |
| route_type_char (rib->type), |
| CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) |
| ? '>' : ' ', |
| CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) |
| ? '*' : ' ', |
| inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ), |
| rn->p.prefixlen); |
| |
| /* Distance and metric display. */ |
| if (rib->type != ZEBRA_ROUTE_CONNECT |
| && rib->type != ZEBRA_ROUTE_KERNEL) |
| len += vty_out (vty, " [%d/%d]", rib->distance, |
| rib->metric); |
| } |
| else |
| vty_out (vty, " %c%*c", |
| CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) |
| ? '*' : ' ', |
| len - 3, ' '); |
| |
| switch (nexthop->type) |
| { |
| case NEXTHOP_TYPE_IPV6: |
| case NEXTHOP_TYPE_IPV6_IFINDEX: |
| case NEXTHOP_TYPE_IPV6_IFNAME: |
| vty_out (vty, " via %s", |
| inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); |
| if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME) |
| vty_out (vty, ", %s", nexthop->ifname); |
| else if (nexthop->ifindex) |
| vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex)); |
| break; |
| case NEXTHOP_TYPE_IFINDEX: |
| vty_out (vty, " is directly connected, %s", |
| ifindex2ifname (nexthop->ifindex)); |
| break; |
| case NEXTHOP_TYPE_IFNAME: |
| vty_out (vty, " is directly connected, %s", |
| nexthop->ifname); |
| break; |
| default: |
| break; |
| } |
| if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) |
| 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; |
| } |
| } |
| |
| if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) |
| vty_out (vty, ", bh"); |
| if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT)) |
| vty_out (vty, ", rej"); |
| |
| if (rib->type == ZEBRA_ROUTE_RIPNG |
| || rib->type == ZEBRA_ROUTE_OSPF6 |
| || rib->type == ZEBRA_ROUTE_ISIS |
| || rib->type == ZEBRA_ROUTE_BGP) |
| { |
| time_t uptime; |
| struct tm *tm; |
| |
| uptime = time (NULL); |
| uptime -= rib->uptime; |
| tm = gmtime (&uptime); |
| |
| #define ONE_DAY_SECOND 60*60*24 |
| #define ONE_WEEK_SECOND 60*60*24*7 |
| |
| if (uptime < ONE_DAY_SECOND) |
| vty_out (vty, ", %02d:%02d:%02d", |
| tm->tm_hour, tm->tm_min, tm->tm_sec); |
| else if (uptime < ONE_WEEK_SECOND) |
| vty_out (vty, ", %dd%02dh%02dm", |
| tm->tm_yday, tm->tm_hour, tm->tm_min); |
| else |
| vty_out (vty, ", %02dw%dd%02dh", |
| tm->tm_yday/7, |
| tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); |
| } |
| vty_out (vty, "%s", VTY_NEWLINE); |
| } |
| } |
| |
| #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", |
| SHOW_STR |
| IP_STR |
| "IPv6 routing table\n") |
| { |
| struct route_table *table; |
| struct route_node *rn; |
| struct rib *rib; |
| int first = 1; |
| |
| table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); |
| if (! table) |
| return CMD_SUCCESS; |
| |
| /* Show all IPv6 route. */ |
| for (rn = route_top (table); rn; rn = route_next (rn)) |
| for (rib = rn->info; rib; rib = rib->next) |
| { |
| if (first) |
| { |
| vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); |
| first = 0; |
| } |
| vty_show_ipv6_route (vty, rn, rib); |
| } |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (show_ipv6_route_prefix_longer, |
| show_ipv6_route_prefix_longer_cmd, |
| "show ipv6 route X:X::X:X/M longer-prefixes", |
| SHOW_STR |
| IP_STR |
| "IPv6 routing table\n" |
| "IPv6 prefix\n" |
| "Show route matching the specified Network/Mask pair only\n") |
| { |
| struct route_table *table; |
| struct route_node *rn; |
| struct rib *rib; |
| struct prefix p; |
| int ret; |
| int first = 1; |
| |
| table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); |
| if (! table) |
| return CMD_SUCCESS; |
| |
| ret = str2prefix (argv[0], &p); |
| if (! ret) |
| { |
| vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| /* Show matched type IPv6 routes. */ |
| for (rn = route_top (table); rn; rn = route_next (rn)) |
| for (rib = rn->info; rib; rib = rib->next) |
| if (prefix_match (&p, &rn->p)) |
| { |
| if (first) |
| { |
| vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); |
| first = 0; |
| } |
| vty_show_ipv6_route (vty, rn, rib); |
| } |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (show_ipv6_route_protocol, |
| show_ipv6_route_protocol_cmd, |
| "show ipv6 route (bgp|connected|isis|kernel|ospf6|ripng|static)", |
| 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") |
| { |
| int type; |
| struct route_table *table; |
| struct route_node *rn; |
| 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 |
| { |
| vty_out (vty, "Unknown route type%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); |
| if (! table) |
| return CMD_SUCCESS; |
| |
| /* Show matched type IPv6 routes. */ |
| for (rn = route_top (table); rn; rn = route_next (rn)) |
| for (rib = rn->info; rib; rib = rib->next) |
| if (rib->type == type) |
| { |
| if (first) |
| { |
| vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); |
| first = 0; |
| } |
| vty_show_ipv6_route (vty, rn, rib); |
| } |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (show_ipv6_route_addr, |
| show_ipv6_route_addr_cmd, |
| "show ipv6 route X:X::X:X", |
| SHOW_STR |
| IP_STR |
| "IPv6 routing table\n" |
| "IPv6 Address\n") |
| { |
| int ret; |
| struct prefix_ipv6 p; |
| struct route_table *table; |
| struct route_node *rn; |
| |
| ret = str2prefix_ipv6 (argv[0], &p); |
| if (ret <= 0) |
| { |
| vty_out (vty, "Malformed IPv6 address%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); |
| if (! table) |
| return CMD_SUCCESS; |
| |
| rn = route_node_match (table, (struct prefix *) &p); |
| if (! rn) |
| { |
| vty_out (vty, "%% Network not in table%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| vty_show_ipv6_route_detail (vty, rn); |
| |
| route_unlock_node (rn); |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (show_ipv6_route_prefix, |
| show_ipv6_route_prefix_cmd, |
| "show ipv6 route X:X::X:X/M", |
| SHOW_STR |
| IP_STR |
| "IPv6 routing table\n" |
| "IPv6 prefix\n") |
| { |
| int ret; |
| struct prefix_ipv6 p; |
| struct route_table *table; |
| struct route_node *rn; |
| |
| ret = str2prefix_ipv6 (argv[0], &p); |
| if (ret <= 0) |
| { |
| vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); |
| if (! table) |
| return CMD_SUCCESS; |
| |
| rn = route_node_match (table, (struct prefix *) &p); |
| if (! rn || rn->p.prefixlen != p.prefixlen) |
| { |
| vty_out (vty, "%% Network not in table%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| vty_show_ipv6_route_detail (vty, rn); |
| |
| route_unlock_node (rn); |
| |
| return CMD_SUCCESS; |
| } |
| |
| |
| /* Write IPv6 static route configuration. */ |
| int |
| static_config_ipv6 (struct vty *vty) |
| { |
| struct route_node *rn; |
| struct static_ipv6 *si; |
| int write; |
| char buf[BUFSIZ]; |
| struct route_table *stable; |
| |
| write = 0; |
| |
| /* Lookup table. */ |
| stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, 0); |
| if (! stable) |
| return -1; |
| |
| for (rn = route_top (stable); rn; rn = route_next (rn)) |
| for (si = rn->info; si; si = si->next) |
| { |
| vty_out (vty, "ipv6 route %s/%d", |
| inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ), |
| rn->p.prefixlen); |
| |
| switch (si->type) |
| { |
| case STATIC_IPV6_GATEWAY: |
| vty_out (vty, " %s", inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ)); |
| break; |
| case STATIC_IPV6_IFNAME: |
| vty_out (vty, " %s", si->ifname); |
| break; |
| case STATIC_IPV6_GATEWAY_IFNAME: |
| vty_out (vty, " %s %s", |
| inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ), si->ifname); |
| break; |
| } |
| |
| if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT)) |
| vty_out (vty, " %s", "reject"); |
| |
| if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) |
| vty_out (vty, " %s", "blackhole"); |
| |
| if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) |
| vty_out (vty, " %d", si->distance); |
| vty_out (vty, "%s", VTY_NEWLINE); |
| |
| write = 1; |
| } |
| return write; |
| } |
| #endif /* HAVE_IPV6 */ |
| |
| /* Static ip route configuration write function. */ |
| int |
| zebra_ip_config (struct vty *vty) |
| { |
| int write = 0; |
| |
| write += static_config_ipv4 (vty); |
| #ifdef HAVE_IPV6 |
| write += static_config_ipv6 (vty); |
| #endif /* HAVE_IPV6 */ |
| |
| return write; |
| } |
| |
| /* IP node for static routes. */ |
| struct cmd_node ip_node = { IP_NODE, "", 1 }; |
| |
| /* Route VTY. */ |
| void |
| zebra_vty_route_init () |
| { |
| install_node (&ip_node, zebra_ip_config); |
| |
| install_element (CONFIG_NODE, &ip_route_cmd); |
| install_element (CONFIG_NODE, &ip_route_flags_cmd); |
| install_element (CONFIG_NODE, &ip_route_flags2_cmd); |
| install_element (CONFIG_NODE, &ip_route_mask_cmd); |
| install_element (CONFIG_NODE, &ip_route_mask_flags_cmd); |
| install_element (CONFIG_NODE, &ip_route_mask_flags2_cmd); |
| install_element (CONFIG_NODE, &no_ip_route_cmd); |
| install_element (CONFIG_NODE, &no_ip_route_flags_cmd); |
| install_element (CONFIG_NODE, &no_ip_route_flags2_cmd); |
| install_element (CONFIG_NODE, &no_ip_route_mask_cmd); |
| install_element (CONFIG_NODE, &no_ip_route_mask_flags_cmd); |
| install_element (CONFIG_NODE, &no_ip_route_mask_flags2_cmd); |
| install_element (CONFIG_NODE, &ip_route_distance_cmd); |
| install_element (CONFIG_NODE, &ip_route_flags_distance_cmd); |
| install_element (CONFIG_NODE, &ip_route_flags_distance2_cmd); |
| install_element (CONFIG_NODE, &ip_route_mask_distance_cmd); |
| install_element (CONFIG_NODE, &ip_route_mask_flags_distance_cmd); |
| install_element (CONFIG_NODE, &ip_route_mask_flags_distance2_cmd); |
| install_element (CONFIG_NODE, &no_ip_route_distance_cmd); |
| install_element (CONFIG_NODE, &no_ip_route_flags_distance_cmd); |
| install_element (CONFIG_NODE, &no_ip_route_flags_distance2_cmd); |
| install_element (CONFIG_NODE, &no_ip_route_mask_flags_distance_cmd); |
| install_element (CONFIG_NODE, &no_ip_route_mask_flags_distance2_cmd); |
| |
| install_element (VIEW_NODE, &show_ip_route_cmd); |
| install_element (VIEW_NODE, &show_ip_route_addr_cmd); |
| install_element (VIEW_NODE, &show_ip_route_prefix_cmd); |
| 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 (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 */ |
| |
| #ifdef HAVE_IPV6 |
| install_element (CONFIG_NODE, &ipv6_route_cmd); |
| install_element (CONFIG_NODE, &ipv6_route_flags_cmd); |
| install_element (CONFIG_NODE, &ipv6_route_ifname_cmd); |
| install_element (CONFIG_NODE, &ipv6_route_ifname_flags_cmd); |
| install_element (CONFIG_NODE, &no_ipv6_route_cmd); |
| install_element (CONFIG_NODE, &no_ipv6_route_flags_cmd); |
| install_element (CONFIG_NODE, &no_ipv6_route_ifname_cmd); |
| install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_cmd); |
| install_element (CONFIG_NODE, &ipv6_route_pref_cmd); |
| install_element (CONFIG_NODE, &ipv6_route_flags_pref_cmd); |
| install_element (CONFIG_NODE, &ipv6_route_ifname_pref_cmd); |
| install_element (CONFIG_NODE, &ipv6_route_ifname_flags_pref_cmd); |
| install_element (CONFIG_NODE, &no_ipv6_route_pref_cmd); |
| install_element (CONFIG_NODE, &no_ipv6_route_flags_pref_cmd); |
| 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_protocol_cmd); |
| install_element (VIEW_NODE, &show_ipv6_route_addr_cmd); |
| install_element (VIEW_NODE, &show_ipv6_route_prefix_cmd); |
| install_element (VIEW_NODE, &show_ipv6_route_prefix_longer_cmd); |
| install_element (ENABLE_NODE, &show_ipv6_route_cmd); |
| install_element (ENABLE_NODE, &show_ipv6_route_protocol_cmd); |
| 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 */ |
| } |
| |
| void |
| zebra_vty_init () |
| { |
| zebra_vty_route_init (); |
| } |