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