1: /* Zebra VTY functions
2: * Copyright (C) 2002 Kunihiro Ishiguro
3: *
4: * This file is part of GNU Zebra.
5: *
6: * GNU Zebra is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2, or (at your option) any
9: * later version.
10: *
11: * GNU Zebra is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * General Public License for more details.
15: *
16: * You should have received a copy of the GNU General Public License
17: * along with GNU Zebra; see the file COPYING. If not, write to the
18: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19: * Boston, MA 02111-1307, USA.
20: */
21:
22: #include <zebra.h>
23:
24: #include "memory.h"
25: #include "if.h"
26: #include "prefix.h"
27: #include "command.h"
28: #include "table.h"
29: #include "rib.h"
30:
31: #include "zebra/zserv.h"
32:
33: /* General fucntion for static route. */
34: static int
35: zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str,
36: const char *mask_str, const char *gate_str,
37: const char *flag_str, const char *distance_str)
38: {
39: int ret;
40: u_char distance;
41: struct prefix p;
42: struct in_addr gate;
43: struct in_addr mask;
44: const char *ifname;
45: u_char flag = 0;
46:
47: ret = str2prefix (dest_str, &p);
48: if (ret <= 0)
49: {
50: vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
51: return CMD_WARNING;
52: }
53:
54: /* Cisco like mask notation. */
55: if (mask_str)
56: {
57: ret = inet_aton (mask_str, &mask);
58: if (ret == 0)
59: {
60: vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
61: return CMD_WARNING;
62: }
63: p.prefixlen = ip_masklen (mask);
64: }
65:
66: /* Apply mask for given prefix. */
67: apply_mask (&p);
68:
69: /* Administrative distance. */
70: if (distance_str)
71: distance = atoi (distance_str);
72: else
73: distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
74:
75: /* Null0 static route. */
76: if ((gate_str != NULL) && (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0))
77: {
78: if (flag_str)
79: {
80: vty_out (vty, "%% can not have flag %s with Null0%s", flag_str, VTY_NEWLINE);
81: return CMD_WARNING;
82: }
83: if (add_cmd)
84: static_add_ipv4 (&p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE, distance, 0);
85: else
86: static_delete_ipv4 (&p, NULL, NULL, distance, 0);
87: return CMD_SUCCESS;
88: }
89:
90: /* Route flags */
91: if (flag_str) {
92: switch(flag_str[0]) {
93: case 'r':
94: case 'R': /* XXX */
95: SET_FLAG (flag, ZEBRA_FLAG_REJECT);
96: break;
97: case 'b':
98: case 'B': /* XXX */
99: SET_FLAG (flag, ZEBRA_FLAG_BLACKHOLE);
100: break;
101: default:
102: vty_out (vty, "%% Malformed flag %s %s", flag_str, VTY_NEWLINE);
103: return CMD_WARNING;
104: }
105: }
106:
107: if (gate_str == NULL)
108: {
109: if (add_cmd)
110: static_add_ipv4 (&p, NULL, NULL, flag, distance, 0);
111: else
112: static_delete_ipv4 (&p, NULL, NULL, distance, 0);
113:
114: return CMD_SUCCESS;
115: }
116:
117: /* When gateway is A.B.C.D format, gate is treated as nexthop
118: address other case gate is treated as interface name. */
119: ret = inet_aton (gate_str, &gate);
120: if (ret)
121: ifname = NULL;
122: else
123: ifname = gate_str;
124:
125: if (add_cmd)
126: static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, distance, 0);
127: else
128: static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, distance, 0);
129:
130: return CMD_SUCCESS;
131: }
132:
133: /* Static route configuration. */
134: DEFUN (ip_route,
135: ip_route_cmd,
136: "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0)",
137: IP_STR
138: "Establish static routes\n"
139: "IP destination prefix (e.g. 10.0.0.0/8)\n"
140: "IP gateway address\n"
141: "IP gateway interface name\n"
142: "Null interface\n")
143: {
144: return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL);
145: }
146:
147: DEFUN (ip_route_flags,
148: ip_route_flags_cmd,
149: "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole)",
150: IP_STR
151: "Establish static routes\n"
152: "IP destination prefix (e.g. 10.0.0.0/8)\n"
153: "IP gateway address\n"
154: "IP gateway interface name\n"
155: "Emit an ICMP unreachable when matched\n"
156: "Silently discard pkts when matched\n")
157: {
158: return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL);
159: }
160:
161: DEFUN (ip_route_flags2,
162: ip_route_flags2_cmd,
163: "ip route A.B.C.D/M (reject|blackhole)",
164: IP_STR
165: "Establish static routes\n"
166: "IP destination prefix (e.g. 10.0.0.0/8)\n"
167: "Emit an ICMP unreachable when matched\n"
168: "Silently discard pkts when matched\n")
169: {
170: return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL);
171: }
172:
173: /* Mask as A.B.C.D format. */
174: DEFUN (ip_route_mask,
175: ip_route_mask_cmd,
176: "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0)",
177: IP_STR
178: "Establish static routes\n"
179: "IP destination prefix\n"
180: "IP destination prefix mask\n"
181: "IP gateway address\n"
182: "IP gateway interface name\n"
183: "Null interface\n")
184: {
185: return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL);
186: }
187:
188: DEFUN (ip_route_mask_flags,
189: ip_route_mask_flags_cmd,
190: "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole)",
191: IP_STR
192: "Establish static routes\n"
193: "IP destination prefix\n"
194: "IP destination prefix mask\n"
195: "IP gateway address\n"
196: "IP gateway interface name\n"
197: "Emit an ICMP unreachable when matched\n"
198: "Silently discard pkts when matched\n")
199: {
200: return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL);
201: }
202:
203: DEFUN (ip_route_mask_flags2,
204: ip_route_mask_flags2_cmd,
205: "ip route A.B.C.D A.B.C.D (reject|blackhole)",
206: IP_STR
207: "Establish static routes\n"
208: "IP destination prefix\n"
209: "IP destination prefix mask\n"
210: "Emit an ICMP unreachable when matched\n"
211: "Silently discard pkts when matched\n")
212: {
213: return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL);
214: }
215:
216: /* Distance option value. */
217: DEFUN (ip_route_distance,
218: ip_route_distance_cmd,
219: "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>",
220: IP_STR
221: "Establish static routes\n"
222: "IP destination prefix (e.g. 10.0.0.0/8)\n"
223: "IP gateway address\n"
224: "IP gateway interface name\n"
225: "Null interface\n"
226: "Distance value for this route\n")
227: {
228: return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2]);
229: }
230:
231: DEFUN (ip_route_flags_distance,
232: ip_route_flags_distance_cmd,
233: "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>",
234: IP_STR
235: "Establish static routes\n"
236: "IP destination prefix (e.g. 10.0.0.0/8)\n"
237: "IP gateway address\n"
238: "IP gateway interface name\n"
239: "Emit an ICMP unreachable when matched\n"
240: "Silently discard pkts when matched\n"
241: "Distance value for this route\n")
242: {
243: return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3]);
244: }
245:
246: DEFUN (ip_route_flags_distance2,
247: ip_route_flags_distance2_cmd,
248: "ip route A.B.C.D/M (reject|blackhole) <1-255>",
249: IP_STR
250: "Establish static routes\n"
251: "IP destination prefix (e.g. 10.0.0.0/8)\n"
252: "Emit an ICMP unreachable when matched\n"
253: "Silently discard pkts when matched\n"
254: "Distance value for this route\n")
255: {
256: return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2]);
257: }
258:
259: DEFUN (ip_route_mask_distance,
260: ip_route_mask_distance_cmd,
261: "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) <1-255>",
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, 1, argv[0], argv[1], argv[2], NULL, argv[3]);
272: }
273:
274: DEFUN (ip_route_mask_flags_distance,
275: ip_route_mask_flags_distance_cmd,
276: "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>",
277: IP_STR
278: "Establish static routes\n"
279: "IP destination prefix\n"
280: "IP destination prefix mask\n"
281: "IP gateway address\n"
282: "IP gateway interface name\n"
283: "Distance value for this route\n"
284: "Emit an ICMP unreachable when matched\n"
285: "Silently discard pkts when matched\n")
286: {
287: return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4]);
288: }
289:
290: DEFUN (ip_route_mask_flags_distance2,
291: ip_route_mask_flags_distance2_cmd,
292: "ip route A.B.C.D A.B.C.D (reject|blackhole) <1-255>",
293: IP_STR
294: "Establish static routes\n"
295: "IP destination prefix\n"
296: "IP destination prefix mask\n"
297: "Distance value for this route\n"
298: "Emit an ICMP unreachable when matched\n"
299: "Silently discard pkts when matched\n")
300: {
301: return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3]);
302: }
303:
304: DEFUN (no_ip_route,
305: no_ip_route_cmd,
306: "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0)",
307: NO_STR
308: IP_STR
309: "Establish static routes\n"
310: "IP destination prefix (e.g. 10.0.0.0/8)\n"
311: "IP gateway address\n"
312: "IP gateway interface name\n"
313: "Null interface\n")
314: {
315: return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL);
316: }
317:
318: ALIAS (no_ip_route,
319: no_ip_route_flags_cmd,
320: "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole)",
321: NO_STR
322: IP_STR
323: "Establish static routes\n"
324: "IP destination prefix (e.g. 10.0.0.0/8)\n"
325: "IP gateway address\n"
326: "IP gateway interface name\n"
327: "Emit an ICMP unreachable when matched\n"
328: "Silently discard pkts when matched\n")
329:
330: DEFUN (no_ip_route_flags2,
331: no_ip_route_flags2_cmd,
332: "no ip route A.B.C.D/M (reject|blackhole)",
333: NO_STR
334: IP_STR
335: "Establish static routes\n"
336: "IP destination prefix (e.g. 10.0.0.0/8)\n"
337: "Emit an ICMP unreachable when matched\n"
338: "Silently discard pkts when matched\n")
339: {
340: return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, NULL);
341: }
342:
343: DEFUN (no_ip_route_mask,
344: no_ip_route_mask_cmd,
345: "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0)",
346: NO_STR
347: IP_STR
348: "Establish static routes\n"
349: "IP destination prefix\n"
350: "IP destination prefix mask\n"
351: "IP gateway address\n"
352: "IP gateway interface name\n"
353: "Null interface\n")
354: {
355: return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL);
356: }
357:
358: ALIAS (no_ip_route_mask,
359: no_ip_route_mask_flags_cmd,
360: "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole)",
361: NO_STR
362: IP_STR
363: "Establish static routes\n"
364: "IP destination prefix\n"
365: "IP destination prefix mask\n"
366: "IP gateway address\n"
367: "IP gateway interface name\n"
368: "Emit an ICMP unreachable when matched\n"
369: "Silently discard pkts when matched\n")
370:
371: DEFUN (no_ip_route_mask_flags2,
372: no_ip_route_mask_flags2_cmd,
373: "no ip route A.B.C.D A.B.C.D (reject|blackhole)",
374: NO_STR
375: IP_STR
376: "Establish static routes\n"
377: "IP destination prefix\n"
378: "IP destination prefix mask\n"
379: "Emit an ICMP unreachable when matched\n"
380: "Silently discard pkts when matched\n")
381: {
382: return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, NULL);
383: }
384:
385: DEFUN (no_ip_route_distance,
386: no_ip_route_distance_cmd,
387: "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>",
388: NO_STR
389: IP_STR
390: "Establish static routes\n"
391: "IP destination prefix (e.g. 10.0.0.0/8)\n"
392: "IP gateway address\n"
393: "IP gateway interface name\n"
394: "Null interface\n"
395: "Distance value for this route\n")
396: {
397: return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2]);
398: }
399:
400: DEFUN (no_ip_route_flags_distance,
401: no_ip_route_flags_distance_cmd,
402: "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>",
403: NO_STR
404: IP_STR
405: "Establish static routes\n"
406: "IP destination prefix (e.g. 10.0.0.0/8)\n"
407: "IP gateway address\n"
408: "IP gateway interface name\n"
409: "Emit an ICMP unreachable when matched\n"
410: "Silently discard pkts when matched\n"
411: "Distance value for this route\n")
412: {
413: return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], argv[3]);
414: }
415:
416: DEFUN (no_ip_route_flags_distance2,
417: no_ip_route_flags_distance2_cmd,
418: "no ip route A.B.C.D/M (reject|blackhole) <1-255>",
419: NO_STR
420: IP_STR
421: "Establish static routes\n"
422: "IP destination prefix (e.g. 10.0.0.0/8)\n"
423: "Emit an ICMP unreachable when matched\n"
424: "Silently discard pkts when matched\n"
425: "Distance value for this route\n")
426: {
427: return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], argv[2]);
428: }
429:
430: DEFUN (no_ip_route_mask_distance,
431: no_ip_route_mask_distance_cmd,
432: "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) <1-255>",
433: NO_STR
434: IP_STR
435: "Establish static routes\n"
436: "IP destination prefix\n"
437: "IP destination prefix mask\n"
438: "IP gateway address\n"
439: "IP gateway interface name\n"
440: "Null interface\n"
441: "Distance value for this route\n")
442: {
443: return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3]);
444: }
445:
446: DEFUN (no_ip_route_mask_flags_distance,
447: no_ip_route_mask_flags_distance_cmd,
448: "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>",
449: NO_STR
450: IP_STR
451: "Establish static routes\n"
452: "IP destination prefix\n"
453: "IP destination prefix mask\n"
454: "IP gateway address\n"
455: "IP gateway interface name\n"
456: "Emit an ICMP unreachable when matched\n"
457: "Silently discard pkts when matched\n"
458: "Distance value for this route\n")
459: {
460: return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4]);
461: }
462:
463: DEFUN (no_ip_route_mask_flags_distance2,
464: no_ip_route_mask_flags_distance2_cmd,
465: "no ip route A.B.C.D A.B.C.D (reject|blackhole) <1-255>",
466: NO_STR
467: IP_STR
468: "Establish static routes\n"
469: "IP destination prefix\n"
470: "IP destination prefix mask\n"
471: "Emit an ICMP unreachable when matched\n"
472: "Silently discard pkts when matched\n"
473: "Distance value for this route\n")
474: {
475: return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3]);
476: }
477:
478: char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1]; /* "any" == ZEBRA_ROUTE_MAX */
479:
480: DEFUN (ip_protocol,
481: ip_protocol_cmd,
482: "ip protocol PROTO route-map ROUTE-MAP",
483: NO_STR
484: "Apply route map to PROTO\n"
485: "Protocol name\n"
486: "Route map name\n")
487: {
488: int i;
489:
490: if (strcasecmp(argv[0], "any") == 0)
491: i = ZEBRA_ROUTE_MAX;
492: else
493: i = proto_name2num(argv[0]);
494: if (i < 0)
495: {
496: vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
497: VTY_NEWLINE);
498: return CMD_WARNING;
499: }
500: if (proto_rm[AFI_IP][i])
501: XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]);
502: proto_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]);
503: return CMD_SUCCESS;
504: }
505:
506: DEFUN (no_ip_protocol,
507: no_ip_protocol_cmd,
508: "no ip protocol PROTO",
509: NO_STR
510: "Remove route map from PROTO\n"
511: "Protocol name\n")
512: {
513: int i;
514:
515: if (strcasecmp(argv[0], "any") == 0)
516: i = ZEBRA_ROUTE_MAX;
517: else
518: i = proto_name2num(argv[0]);
519: if (i < 0)
520: {
521: vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
522: VTY_NEWLINE);
523: return CMD_WARNING;
524: }
525: if (proto_rm[AFI_IP][i])
526: XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]);
527: proto_rm[AFI_IP][i] = NULL;
528: return CMD_SUCCESS;
529: }
530:
531: /* New RIB. Detailed information for IPv4 route. */
532: static void
533: vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
534: {
535: struct rib *rib;
536: struct nexthop *nexthop;
537:
538: RNODE_FOREACH_RIB (rn, rib)
539: {
540: vty_out (vty, "Routing entry for %s/%d%s",
541: inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
542: VTY_NEWLINE);
543: vty_out (vty, " Known via \"%s\"", zebra_route_string (rib->type));
544: vty_out (vty, ", distance %u, metric %u", rib->distance, rib->metric);
545: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
546: vty_out (vty, ", best");
547: if (rib->refcnt)
548: vty_out (vty, ", refcnt %ld", rib->refcnt);
549: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
550: vty_out (vty, ", blackhole");
551: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT))
552: vty_out (vty, ", reject");
553: vty_out (vty, "%s", VTY_NEWLINE);
554:
555: #define ONE_DAY_SECOND 60*60*24
556: #define ONE_WEEK_SECOND 60*60*24*7
557: if (rib->type == ZEBRA_ROUTE_RIP
558: || rib->type == ZEBRA_ROUTE_OSPF
559: || rib->type == ZEBRA_ROUTE_BABEL
560: || rib->type == ZEBRA_ROUTE_ISIS
561: || rib->type == ZEBRA_ROUTE_BGP)
562: {
563: time_t uptime;
564: struct tm *tm;
565:
566: uptime = time (NULL);
567: uptime -= rib->uptime;
568: tm = gmtime (&uptime);
569:
570: vty_out (vty, " Last update ");
571:
572: if (uptime < ONE_DAY_SECOND)
573: vty_out (vty, "%02d:%02d:%02d",
574: tm->tm_hour, tm->tm_min, tm->tm_sec);
575: else if (uptime < ONE_WEEK_SECOND)
576: vty_out (vty, "%dd%02dh%02dm",
577: tm->tm_yday, tm->tm_hour, tm->tm_min);
578: else
579: vty_out (vty, "%02dw%dd%02dh",
580: tm->tm_yday/7,
581: tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
582: vty_out (vty, " ago%s", VTY_NEWLINE);
583: }
584:
585: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
586: {
587: char addrstr[32];
588:
589: vty_out (vty, " %c",
590: CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
591:
592: switch (nexthop->type)
593: {
594: case NEXTHOP_TYPE_IPV4:
595: case NEXTHOP_TYPE_IPV4_IFINDEX:
596: vty_out (vty, " %s", inet_ntoa (nexthop->gate.ipv4));
597: if (nexthop->ifindex)
598: vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex));
599: break;
600: case NEXTHOP_TYPE_IFINDEX:
601: vty_out (vty, " directly connected, %s",
602: ifindex2ifname (nexthop->ifindex));
603: break;
604: case NEXTHOP_TYPE_IFNAME:
605: vty_out (vty, " directly connected, %s", nexthop->ifname);
606: break;
607: case NEXTHOP_TYPE_BLACKHOLE:
608: vty_out (vty, " directly connected, Null0");
609: break;
610: default:
611: break;
612: }
613: if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
614: vty_out (vty, " inactive");
615:
616: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
617: {
618: vty_out (vty, " (recursive");
619:
620: switch (nexthop->rtype)
621: {
622: case NEXTHOP_TYPE_IPV4:
623: case NEXTHOP_TYPE_IPV4_IFINDEX:
624: vty_out (vty, " via %s)", inet_ntoa (nexthop->rgate.ipv4));
625: break;
626: case NEXTHOP_TYPE_IFINDEX:
627: case NEXTHOP_TYPE_IFNAME:
628: vty_out (vty, " is directly connected, %s)",
629: ifindex2ifname (nexthop->rifindex));
630: break;
631: default:
632: break;
633: }
634: }
635: switch (nexthop->type)
636: {
637: case NEXTHOP_TYPE_IPV4:
638: case NEXTHOP_TYPE_IPV4_IFINDEX:
639: case NEXTHOP_TYPE_IPV4_IFNAME:
640: if (nexthop->src.ipv4.s_addr)
641: {
642: if (inet_ntop(AF_INET, &nexthop->src.ipv4, addrstr,
643: sizeof addrstr))
644: vty_out (vty, ", src %s", addrstr);
645: }
646: break;
647: #ifdef HAVE_IPV6
648: case NEXTHOP_TYPE_IPV6:
649: case NEXTHOP_TYPE_IPV6_IFINDEX:
650: case NEXTHOP_TYPE_IPV6_IFNAME:
651: if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
652: {
653: if (inet_ntop(AF_INET6, &nexthop->src.ipv6, addrstr,
654: sizeof addrstr))
655: vty_out (vty, ", src %s", addrstr);
656: }
657: break;
658: #endif /* HAVE_IPV6 */
659: default:
660: break;
661: }
662: vty_out (vty, "%s", VTY_NEWLINE);
663: }
664: vty_out (vty, "%s", VTY_NEWLINE);
665: }
666: }
667:
668: static void
669: vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
670: {
671: struct nexthop *nexthop;
672: int len = 0;
673: char buf[BUFSIZ];
674:
675: /* Nexthop information. */
676: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
677: {
678: if (nexthop == rib->nexthop)
679: {
680: /* Prefix information. */
681: len = vty_out (vty, "%c%c%c %s/%d",
682: zebra_route_char (rib->type),
683: CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)
684: ? '>' : ' ',
685: CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
686: ? '*' : ' ',
687: inet_ntop (AF_INET, &rn->p.u.prefix, buf, BUFSIZ),
688: rn->p.prefixlen);
689:
690: /* Distance and metric display. */
691: if (rib->type != ZEBRA_ROUTE_CONNECT
692: && rib->type != ZEBRA_ROUTE_KERNEL)
693: len += vty_out (vty, " [%d/%d]", rib->distance,
694: rib->metric);
695: }
696: else
697: vty_out (vty, " %c%*c",
698: CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
699: ? '*' : ' ',
700: len - 3, ' ');
701:
702: switch (nexthop->type)
703: {
704: case NEXTHOP_TYPE_IPV4:
705: case NEXTHOP_TYPE_IPV4_IFINDEX:
706: vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4));
707: if (nexthop->ifindex)
708: vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex));
709: break;
710: case NEXTHOP_TYPE_IFINDEX:
711: vty_out (vty, " is directly connected, %s",
712: ifindex2ifname (nexthop->ifindex));
713: break;
714: case NEXTHOP_TYPE_IFNAME:
715: vty_out (vty, " is directly connected, %s", nexthop->ifname);
716: break;
717: case NEXTHOP_TYPE_BLACKHOLE:
718: vty_out (vty, " is directly connected, Null0");
719: break;
720: default:
721: break;
722: }
723: if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
724: vty_out (vty, " inactive");
725:
726: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
727: {
728: vty_out (vty, " (recursive");
729:
730: switch (nexthop->rtype)
731: {
732: case NEXTHOP_TYPE_IPV4:
733: case NEXTHOP_TYPE_IPV4_IFINDEX:
734: vty_out (vty, " via %s)", inet_ntoa (nexthop->rgate.ipv4));
735: break;
736: case NEXTHOP_TYPE_IFINDEX:
737: case NEXTHOP_TYPE_IFNAME:
738: vty_out (vty, " is directly connected, %s)",
739: ifindex2ifname (nexthop->rifindex));
740: break;
741: default:
742: break;
743: }
744: }
745: switch (nexthop->type)
746: {
747: case NEXTHOP_TYPE_IPV4:
748: case NEXTHOP_TYPE_IPV4_IFINDEX:
749: case NEXTHOP_TYPE_IPV4_IFNAME:
750: if (nexthop->src.ipv4.s_addr)
751: {
752: if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, sizeof buf))
753: vty_out (vty, ", src %s", buf);
754: }
755: break;
756: #ifdef HAVE_IPV6
757: case NEXTHOP_TYPE_IPV6:
758: case NEXTHOP_TYPE_IPV6_IFINDEX:
759: case NEXTHOP_TYPE_IPV6_IFNAME:
760: if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
761: {
762: if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, sizeof buf))
763: vty_out (vty, ", src %s", buf);
764: }
765: break;
766: #endif /* HAVE_IPV6 */
767: default:
768: break;
769: }
770:
771: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
772: vty_out (vty, ", bh");
773: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT))
774: vty_out (vty, ", rej");
775:
776: if (rib->type == ZEBRA_ROUTE_RIP
777: || rib->type == ZEBRA_ROUTE_OSPF
778: || rib->type == ZEBRA_ROUTE_BABEL
779: || rib->type == ZEBRA_ROUTE_ISIS
780: || rib->type == ZEBRA_ROUTE_BGP)
781: {
782: time_t uptime;
783: struct tm *tm;
784:
785: uptime = time (NULL);
786: uptime -= rib->uptime;
787: tm = gmtime (&uptime);
788:
789: #define ONE_DAY_SECOND 60*60*24
790: #define ONE_WEEK_SECOND 60*60*24*7
791:
792: if (uptime < ONE_DAY_SECOND)
793: vty_out (vty, ", %02d:%02d:%02d",
794: tm->tm_hour, tm->tm_min, tm->tm_sec);
795: else if (uptime < ONE_WEEK_SECOND)
796: vty_out (vty, ", %dd%02dh%02dm",
797: tm->tm_yday, tm->tm_hour, tm->tm_min);
798: else
799: vty_out (vty, ", %02dw%dd%02dh",
800: tm->tm_yday/7,
801: tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
802: }
803: vty_out (vty, "%s", VTY_NEWLINE);
804: }
805: }
806:
807: DEFUN (show_ip_route,
808: show_ip_route_cmd,
809: "show ip route",
810: SHOW_STR
811: IP_STR
812: "IP routing table\n")
813: {
814: struct route_table *table;
815: struct route_node *rn;
816: struct rib *rib;
817: int first = 1;
818:
819: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
820: if (! table)
821: return CMD_SUCCESS;
822:
823: /* Show all IPv4 routes. */
824: for (rn = route_top (table); rn; rn = route_next (rn))
825: RNODE_FOREACH_RIB (rn, rib)
826: {
827: if (first)
828: {
829: vty_out (vty, SHOW_ROUTE_V4_HEADER);
830: first = 0;
831: }
832: vty_show_ip_route (vty, rn, rib);
833: }
834: return CMD_SUCCESS;
835: }
836:
837: DEFUN (show_ip_route_prefix_longer,
838: show_ip_route_prefix_longer_cmd,
839: "show ip route A.B.C.D/M longer-prefixes",
840: SHOW_STR
841: IP_STR
842: "IP routing table\n"
843: "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
844: "Show route matching the specified Network/Mask pair only\n")
845: {
846: struct route_table *table;
847: struct route_node *rn;
848: struct rib *rib;
849: struct prefix p;
850: int ret;
851: int first = 1;
852:
853: ret = str2prefix (argv[0], &p);
854: if (! ret)
855: {
856: vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
857: return CMD_WARNING;
858: }
859:
860: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
861: if (! table)
862: return CMD_SUCCESS;
863:
864: /* Show matched type IPv4 routes. */
865: for (rn = route_top (table); rn; rn = route_next (rn))
866: RNODE_FOREACH_RIB (rn, rib)
867: if (prefix_match (&p, &rn->p))
868: {
869: if (first)
870: {
871: vty_out (vty, SHOW_ROUTE_V4_HEADER);
872: first = 0;
873: }
874: vty_show_ip_route (vty, rn, rib);
875: }
876: return CMD_SUCCESS;
877: }
878:
879: DEFUN (show_ip_route_supernets,
880: show_ip_route_supernets_cmd,
881: "show ip route supernets-only",
882: SHOW_STR
883: IP_STR
884: "IP routing table\n"
885: "Show supernet entries only\n")
886: {
887: struct route_table *table;
888: struct route_node *rn;
889: struct rib *rib;
890: u_int32_t addr;
891: int first = 1;
892:
893: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
894: if (! table)
895: return CMD_SUCCESS;
896:
897: /* Show matched type IPv4 routes. */
898: for (rn = route_top (table); rn; rn = route_next (rn))
899: RNODE_FOREACH_RIB (rn, rib)
900: {
901: addr = ntohl (rn->p.u.prefix4.s_addr);
902:
903: if ((IN_CLASSC (addr) && rn->p.prefixlen < 24)
904: || (IN_CLASSB (addr) && rn->p.prefixlen < 16)
905: || (IN_CLASSA (addr) && rn->p.prefixlen < 8))
906: {
907: if (first)
908: {
909: vty_out (vty, SHOW_ROUTE_V4_HEADER);
910: first = 0;
911: }
912: vty_show_ip_route (vty, rn, rib);
913: }
914: }
915: return CMD_SUCCESS;
916: }
917:
918: DEFUN (show_ip_route_protocol,
919: show_ip_route_protocol_cmd,
920: "show ip route " QUAGGA_IP_REDIST_STR_ZEBRA,
921: SHOW_STR
922: IP_STR
923: "IP routing table\n"
924: QUAGGA_IP_REDIST_HELP_STR_ZEBRA)
925: {
926: int type;
927: struct route_table *table;
928: struct route_node *rn;
929: struct rib *rib;
930: int first = 1;
931:
932: type = proto_redistnum (AFI_IP, argv[0]);
933: if (type < 0)
934: {
935: vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
936: return CMD_WARNING;
937: }
938:
939: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
940: if (! table)
941: return CMD_SUCCESS;
942:
943: /* Show matched type IPv4 routes. */
944: for (rn = route_top (table); rn; rn = route_next (rn))
945: RNODE_FOREACH_RIB (rn, rib)
946: if (rib->type == type)
947: {
948: if (first)
949: {
950: vty_out (vty, SHOW_ROUTE_V4_HEADER);
951: first = 0;
952: }
953: vty_show_ip_route (vty, rn, rib);
954: }
955: return CMD_SUCCESS;
956: }
957:
958: DEFUN (show_ip_route_addr,
959: show_ip_route_addr_cmd,
960: "show ip route A.B.C.D",
961: SHOW_STR
962: IP_STR
963: "IP routing table\n"
964: "Network in the IP routing table to display\n")
965: {
966: int ret;
967: struct prefix_ipv4 p;
968: struct route_table *table;
969: struct route_node *rn;
970:
971: ret = str2prefix_ipv4 (argv[0], &p);
972: if (ret <= 0)
973: {
974: vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE);
975: return CMD_WARNING;
976: }
977:
978: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
979: if (! table)
980: return CMD_SUCCESS;
981:
982: rn = route_node_match (table, (struct prefix *) &p);
983: if (! rn)
984: {
985: vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
986: return CMD_WARNING;
987: }
988:
989: vty_show_ip_route_detail (vty, rn);
990:
991: route_unlock_node (rn);
992:
993: return CMD_SUCCESS;
994: }
995:
996: DEFUN (show_ip_route_prefix,
997: show_ip_route_prefix_cmd,
998: "show ip route A.B.C.D/M",
999: SHOW_STR
1000: IP_STR
1001: "IP routing table\n"
1002: "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
1003: {
1004: int ret;
1005: struct prefix_ipv4 p;
1006: struct route_table *table;
1007: struct route_node *rn;
1008:
1009: ret = str2prefix_ipv4 (argv[0], &p);
1010: if (ret <= 0)
1011: {
1012: vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE);
1013: return CMD_WARNING;
1014: }
1015:
1016: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1017: if (! table)
1018: return CMD_SUCCESS;
1019:
1020: rn = route_node_match (table, (struct prefix *) &p);
1021: if (! rn || rn->p.prefixlen != p.prefixlen)
1022: {
1023: vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
1024: return CMD_WARNING;
1025: }
1026:
1027: vty_show_ip_route_detail (vty, rn);
1028:
1029: route_unlock_node (rn);
1030:
1031: return CMD_SUCCESS;
1032: }
1033:
1034: static void
1035: vty_show_ip_route_summary (struct vty *vty, struct route_table *table)
1036: {
1037: struct route_node *rn;
1038: struct rib *rib;
1039: struct nexthop *nexthop;
1040: #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
1041: #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
1042: u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1043: u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1044: u_int32_t i;
1045:
1046: memset (&rib_cnt, 0, sizeof(rib_cnt));
1047: memset (&fib_cnt, 0, sizeof(fib_cnt));
1048: for (rn = route_top (table); rn; rn = route_next (rn))
1049: RNODE_FOREACH_RIB (rn, rib)
1050: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1051: {
1052: rib_cnt[ZEBRA_ROUTE_TOTAL]++;
1053: rib_cnt[rib->type]++;
1054: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1055: {
1056: fib_cnt[ZEBRA_ROUTE_TOTAL]++;
1057: fib_cnt[rib->type]++;
1058: }
1059: if (rib->type == ZEBRA_ROUTE_BGP &&
1060: CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1061: {
1062: rib_cnt[ZEBRA_ROUTE_IBGP]++;
1063: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1064: fib_cnt[ZEBRA_ROUTE_IBGP]++;
1065: }
1066: }
1067:
1068: vty_out (vty, "%-20s %-20s %-20s %s",
1069: "Route Source", "Routes", "FIB", VTY_NEWLINE);
1070:
1071: for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
1072: {
1073: if (rib_cnt[i] > 0)
1074: {
1075: if (i == ZEBRA_ROUTE_BGP)
1076: {
1077: vty_out (vty, "%-20s %-20d %-20d %s", "ebgp",
1078: rib_cnt[ZEBRA_ROUTE_BGP] - rib_cnt[ZEBRA_ROUTE_IBGP],
1079: fib_cnt[ZEBRA_ROUTE_BGP] - fib_cnt[ZEBRA_ROUTE_IBGP],
1080: VTY_NEWLINE);
1081: vty_out (vty, "%-20s %-20d %-20d %s", "ibgp",
1082: rib_cnt[ZEBRA_ROUTE_IBGP], fib_cnt[ZEBRA_ROUTE_IBGP],
1083: VTY_NEWLINE);
1084: }
1085: else
1086: vty_out (vty, "%-20s %-20d %-20d %s", zebra_route_string(i),
1087: rib_cnt[i], fib_cnt[i], VTY_NEWLINE);
1088: }
1089: }
1090:
1091: vty_out (vty, "------%s", VTY_NEWLINE);
1092: vty_out (vty, "%-20s %-20d %-20d %s", "Totals", rib_cnt[ZEBRA_ROUTE_TOTAL],
1093: fib_cnt[ZEBRA_ROUTE_TOTAL], VTY_NEWLINE);
1094: }
1095:
1096: /* Show route summary. */
1097: DEFUN (show_ip_route_summary,
1098: show_ip_route_summary_cmd,
1099: "show ip route summary",
1100: SHOW_STR
1101: IP_STR
1102: "IP routing table\n"
1103: "Summary of all routes\n")
1104: {
1105: struct route_table *table;
1106:
1107: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1108: if (! table)
1109: return CMD_SUCCESS;
1110:
1111: vty_show_ip_route_summary (vty, table);
1112:
1113: return CMD_SUCCESS;
1114: }
1115:
1116: /* Write IPv4 static route configuration. */
1117: static int
1118: static_config_ipv4 (struct vty *vty)
1119: {
1120: struct route_node *rn;
1121: struct static_ipv4 *si;
1122: struct route_table *stable;
1123: int write;
1124:
1125: write = 0;
1126:
1127: /* Lookup table. */
1128: stable = vrf_static_table (AFI_IP, SAFI_UNICAST, 0);
1129: if (! stable)
1130: return -1;
1131:
1132: for (rn = route_top (stable); rn; rn = route_next (rn))
1133: for (si = rn->info; si; si = si->next)
1134: {
1135: vty_out (vty, "ip route %s/%d", inet_ntoa (rn->p.u.prefix4),
1136: rn->p.prefixlen);
1137:
1138: switch (si->type)
1139: {
1140: case STATIC_IPV4_GATEWAY:
1141: vty_out (vty, " %s", inet_ntoa (si->gate.ipv4));
1142: break;
1143: case STATIC_IPV4_IFNAME:
1144: vty_out (vty, " %s", si->gate.ifname);
1145: break;
1146: case STATIC_IPV4_BLACKHOLE:
1147: vty_out (vty, " Null0");
1148: break;
1149: }
1150:
1151: /* flags are incompatible with STATIC_IPV4_BLACKHOLE */
1152: if (si->type != STATIC_IPV4_BLACKHOLE)
1153: {
1154: if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT))
1155: vty_out (vty, " %s", "reject");
1156:
1157: if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE))
1158: vty_out (vty, " %s", "blackhole");
1159: }
1160:
1161: if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
1162: vty_out (vty, " %d", si->distance);
1163:
1164: vty_out (vty, "%s", VTY_NEWLINE);
1165:
1166: write = 1;
1167: }
1168: return write;
1169: }
1170:
1171: DEFUN (show_ip_protocol,
1172: show_ip_protocol_cmd,
1173: "show ip protocol",
1174: SHOW_STR
1175: IP_STR
1176: "IP protocol filtering status\n")
1177: {
1178: int i;
1179:
1180: vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE);
1181: vty_out(vty, "------------------------%s", VTY_NEWLINE);
1182: for (i=0;i<ZEBRA_ROUTE_MAX;i++)
1183: {
1184: if (proto_rm[AFI_IP][i])
1185: vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i),
1186: proto_rm[AFI_IP][i],
1187: VTY_NEWLINE);
1188: else
1189: vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE);
1190: }
1191: if (proto_rm[AFI_IP][i])
1192: vty_out (vty, "%-10s : %-10s%s", "any", proto_rm[AFI_IP][i],
1193: VTY_NEWLINE);
1194: else
1195: vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE);
1196:
1197: return CMD_SUCCESS;
1198: }
1199:
1200: /*
1201: * Show IP mroute command to dump the BGP Multicast
1202: * routing table
1203: */
1204: DEFUN (show_ip_mroute,
1205: show_ip_mroute_cmd,
1206: "show ip mroute",
1207: SHOW_STR
1208: IP_STR
1209: "IP Multicast routing table\n")
1210: {
1211: struct route_table *table;
1212: struct route_node *rn;
1213: struct rib *rib;
1214: int first = 1;
1215:
1216: table = vrf_table (AFI_IP, SAFI_MULTICAST, 0);
1217: if (! table)
1218: return CMD_SUCCESS;
1219:
1220: /* Show all IPv4 routes. */
1221: for (rn = route_top (table); rn; rn = route_next (rn))
1222: RNODE_FOREACH_RIB (rn, rib)
1223: {
1224: if (first)
1225: {
1226: vty_out (vty, SHOW_ROUTE_V4_HEADER);
1227: first = 0;
1228: }
1229: vty_show_ip_route (vty, rn, rib);
1230: }
1231: return CMD_SUCCESS;
1232: }
1233:
1234:
1235: #ifdef HAVE_IPV6
1236: /* General fucntion for IPv6 static route. */
1237: static int
1238: static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str,
1239: const char *gate_str, const char *ifname,
1240: const char *flag_str, const char *distance_str)
1241: {
1242: int ret;
1243: u_char distance;
1244: struct prefix p;
1245: struct in6_addr *gate = NULL;
1246: struct in6_addr gate_addr;
1247: u_char type = 0;
1248: int table = 0;
1249: u_char flag = 0;
1250:
1251: ret = str2prefix (dest_str, &p);
1252: if (ret <= 0)
1253: {
1254: vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
1255: return CMD_WARNING;
1256: }
1257:
1258: /* Apply mask for given prefix. */
1259: apply_mask (&p);
1260:
1261: /* Route flags */
1262: if (flag_str) {
1263: switch(flag_str[0]) {
1264: case 'r':
1265: case 'R': /* XXX */
1266: SET_FLAG (flag, ZEBRA_FLAG_REJECT);
1267: break;
1268: case 'b':
1269: case 'B': /* XXX */
1270: SET_FLAG (flag, ZEBRA_FLAG_BLACKHOLE);
1271: break;
1272: default:
1273: vty_out (vty, "%% Malformed flag %s %s", flag_str, VTY_NEWLINE);
1274: return CMD_WARNING;
1275: }
1276: }
1277:
1278: /* Administrative distance. */
1279: if (distance_str)
1280: distance = atoi (distance_str);
1281: else
1282: distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
1283:
1284: /* When gateway is valid IPv6 addrees, then gate is treated as
1285: nexthop address other case gate is treated as interface name. */
1286: ret = inet_pton (AF_INET6, gate_str, &gate_addr);
1287:
1288: if (ifname)
1289: {
1290: /* When ifname is specified. It must be come with gateway
1291: address. */
1292: if (ret != 1)
1293: {
1294: vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
1295: return CMD_WARNING;
1296: }
1297: type = STATIC_IPV6_GATEWAY_IFNAME;
1298: gate = &gate_addr;
1299: }
1300: else
1301: {
1302: if (ret == 1)
1303: {
1304: type = STATIC_IPV6_GATEWAY;
1305: gate = &gate_addr;
1306: }
1307: else
1308: {
1309: type = STATIC_IPV6_IFNAME;
1310: ifname = gate_str;
1311: }
1312: }
1313:
1314: if (add_cmd)
1315: static_add_ipv6 (&p, type, gate, ifname, flag, distance, table);
1316: else
1317: static_delete_ipv6 (&p, type, gate, ifname, distance, table);
1318:
1319: return CMD_SUCCESS;
1320: }
1321:
1322: DEFUN (ipv6_route,
1323: ipv6_route_cmd,
1324: "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)",
1325: IP_STR
1326: "Establish static routes\n"
1327: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1328: "IPv6 gateway address\n"
1329: "IPv6 gateway interface name\n")
1330: {
1331: return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL);
1332: }
1333:
1334: DEFUN (ipv6_route_flags,
1335: ipv6_route_flags_cmd,
1336: "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)",
1337: IP_STR
1338: "Establish static routes\n"
1339: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1340: "IPv6 gateway address\n"
1341: "IPv6 gateway interface name\n"
1342: "Emit an ICMP unreachable when matched\n"
1343: "Silently discard pkts when matched\n")
1344: {
1345: return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL);
1346: }
1347:
1348: DEFUN (ipv6_route_ifname,
1349: ipv6_route_ifname_cmd,
1350: "ipv6 route X:X::X:X/M X:X::X:X INTERFACE",
1351: IP_STR
1352: "Establish static routes\n"
1353: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1354: "IPv6 gateway address\n"
1355: "IPv6 gateway interface name\n")
1356: {
1357: return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL);
1358: }
1359:
1360: DEFUN (ipv6_route_ifname_flags,
1361: ipv6_route_ifname_flags_cmd,
1362: "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)",
1363: IP_STR
1364: "Establish static routes\n"
1365: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1366: "IPv6 gateway address\n"
1367: "IPv6 gateway interface name\n"
1368: "Emit an ICMP unreachable when matched\n"
1369: "Silently discard pkts when matched\n")
1370: {
1371: return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL);
1372: }
1373:
1374: DEFUN (ipv6_route_pref,
1375: ipv6_route_pref_cmd,
1376: "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>",
1377: IP_STR
1378: "Establish static routes\n"
1379: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1380: "IPv6 gateway address\n"
1381: "IPv6 gateway interface name\n"
1382: "Distance value for this prefix\n")
1383: {
1384: return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2]);
1385: }
1386:
1387: DEFUN (ipv6_route_flags_pref,
1388: ipv6_route_flags_pref_cmd,
1389: "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>",
1390: IP_STR
1391: "Establish static routes\n"
1392: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1393: "IPv6 gateway address\n"
1394: "IPv6 gateway interface name\n"
1395: "Emit an ICMP unreachable when matched\n"
1396: "Silently discard pkts when matched\n"
1397: "Distance value for this prefix\n")
1398: {
1399: return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3]);
1400: }
1401:
1402: DEFUN (ipv6_route_ifname_pref,
1403: ipv6_route_ifname_pref_cmd,
1404: "ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>",
1405: IP_STR
1406: "Establish static routes\n"
1407: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1408: "IPv6 gateway address\n"
1409: "IPv6 gateway interface name\n"
1410: "Distance value for this prefix\n")
1411: {
1412: return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3]);
1413: }
1414:
1415: DEFUN (ipv6_route_ifname_flags_pref,
1416: ipv6_route_ifname_flags_pref_cmd,
1417: "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>",
1418: IP_STR
1419: "Establish static routes\n"
1420: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1421: "IPv6 gateway address\n"
1422: "IPv6 gateway interface name\n"
1423: "Emit an ICMP unreachable when matched\n"
1424: "Silently discard pkts when matched\n"
1425: "Distance value for this prefix\n")
1426: {
1427: return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4]);
1428: }
1429:
1430: DEFUN (no_ipv6_route,
1431: no_ipv6_route_cmd,
1432: "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)",
1433: NO_STR
1434: IP_STR
1435: "Establish static routes\n"
1436: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1437: "IPv6 gateway address\n"
1438: "IPv6 gateway interface name\n")
1439: {
1440: return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL);
1441: }
1442:
1443: ALIAS (no_ipv6_route,
1444: no_ipv6_route_flags_cmd,
1445: "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)",
1446: NO_STR
1447: IP_STR
1448: "Establish static routes\n"
1449: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1450: "IPv6 gateway address\n"
1451: "IPv6 gateway interface name\n"
1452: "Emit an ICMP unreachable when matched\n"
1453: "Silently discard pkts when matched\n")
1454:
1455: DEFUN (no_ipv6_route_ifname,
1456: no_ipv6_route_ifname_cmd,
1457: "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE",
1458: NO_STR
1459: IP_STR
1460: "Establish static routes\n"
1461: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1462: "IPv6 gateway address\n"
1463: "IPv6 gateway interface name\n")
1464: {
1465: return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL);
1466: }
1467:
1468: ALIAS (no_ipv6_route_ifname,
1469: no_ipv6_route_ifname_flags_cmd,
1470: "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)",
1471: NO_STR
1472: IP_STR
1473: "Establish static routes\n"
1474: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1475: "IPv6 gateway address\n"
1476: "IPv6 gateway interface name\n"
1477: "Emit an ICMP unreachable when matched\n"
1478: "Silently discard pkts when matched\n")
1479:
1480: DEFUN (no_ipv6_route_pref,
1481: no_ipv6_route_pref_cmd,
1482: "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>",
1483: NO_STR
1484: IP_STR
1485: "Establish static routes\n"
1486: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1487: "IPv6 gateway address\n"
1488: "IPv6 gateway interface name\n"
1489: "Distance value for this prefix\n")
1490: {
1491: return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2]);
1492: }
1493:
1494: DEFUN (no_ipv6_route_flags_pref,
1495: no_ipv6_route_flags_pref_cmd,
1496: "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>",
1497: NO_STR
1498: IP_STR
1499: "Establish static routes\n"
1500: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1501: "IPv6 gateway address\n"
1502: "IPv6 gateway interface name\n"
1503: "Emit an ICMP unreachable when matched\n"
1504: "Silently discard pkts when matched\n"
1505: "Distance value for this prefix\n")
1506: {
1507: /* We do not care about argv[2] */
1508: return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3]);
1509: }
1510:
1511: DEFUN (no_ipv6_route_ifname_pref,
1512: no_ipv6_route_ifname_pref_cmd,
1513: "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>",
1514: NO_STR
1515: IP_STR
1516: "Establish static routes\n"
1517: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1518: "IPv6 gateway address\n"
1519: "IPv6 gateway interface name\n"
1520: "Distance value for this prefix\n")
1521: {
1522: return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3]);
1523: }
1524:
1525: DEFUN (no_ipv6_route_ifname_flags_pref,
1526: no_ipv6_route_ifname_flags_pref_cmd,
1527: "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>",
1528: NO_STR
1529: IP_STR
1530: "Establish static routes\n"
1531: "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1532: "IPv6 gateway address\n"
1533: "IPv6 gateway interface name\n"
1534: "Emit an ICMP unreachable when matched\n"
1535: "Silently discard pkts when matched\n"
1536: "Distance value for this prefix\n")
1537: {
1538: return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4]);
1539: }
1540:
1541: /* New RIB. Detailed information for IPv6 route. */
1542: static void
1543: vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn)
1544: {
1545: struct rib *rib;
1546: struct nexthop *nexthop;
1547: char buf[BUFSIZ];
1548:
1549: RNODE_FOREACH_RIB (rn, rib)
1550: {
1551: vty_out (vty, "Routing entry for %s/%d%s",
1552: inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
1553: rn->p.prefixlen,
1554: VTY_NEWLINE);
1555: vty_out (vty, " Known via \"%s\"", zebra_route_string (rib->type));
1556: vty_out (vty, ", distance %u, metric %u", rib->distance, rib->metric);
1557: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1558: vty_out (vty, ", best");
1559: if (rib->refcnt)
1560: vty_out (vty, ", refcnt %ld", rib->refcnt);
1561: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
1562: vty_out (vty, ", blackhole");
1563: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT))
1564: vty_out (vty, ", reject");
1565: vty_out (vty, "%s", VTY_NEWLINE);
1566:
1567: #define ONE_DAY_SECOND 60*60*24
1568: #define ONE_WEEK_SECOND 60*60*24*7
1569: if (rib->type == ZEBRA_ROUTE_RIPNG
1570: || rib->type == ZEBRA_ROUTE_OSPF6
1571: || rib->type == ZEBRA_ROUTE_BABEL
1572: || rib->type == ZEBRA_ROUTE_ISIS
1573: || rib->type == ZEBRA_ROUTE_BGP)
1574: {
1575: time_t uptime;
1576: struct tm *tm;
1577:
1578: uptime = time (NULL);
1579: uptime -= rib->uptime;
1580: tm = gmtime (&uptime);
1581:
1582: vty_out (vty, " Last update ");
1583:
1584: if (uptime < ONE_DAY_SECOND)
1585: vty_out (vty, "%02d:%02d:%02d",
1586: tm->tm_hour, tm->tm_min, tm->tm_sec);
1587: else if (uptime < ONE_WEEK_SECOND)
1588: vty_out (vty, "%dd%02dh%02dm",
1589: tm->tm_yday, tm->tm_hour, tm->tm_min);
1590: else
1591: vty_out (vty, "%02dw%dd%02dh",
1592: tm->tm_yday/7,
1593: tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
1594: vty_out (vty, " ago%s", VTY_NEWLINE);
1595: }
1596:
1597: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1598: {
1599: vty_out (vty, " %c",
1600: CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
1601:
1602: switch (nexthop->type)
1603: {
1604: case NEXTHOP_TYPE_IPV6:
1605: case NEXTHOP_TYPE_IPV6_IFINDEX:
1606: case NEXTHOP_TYPE_IPV6_IFNAME:
1607: vty_out (vty, " %s",
1608: inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
1609: if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1610: vty_out (vty, ", %s", nexthop->ifname);
1611: else if (nexthop->ifindex)
1612: vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex));
1613: break;
1614: case NEXTHOP_TYPE_IFINDEX:
1615: vty_out (vty, " directly connected, %s",
1616: ifindex2ifname (nexthop->ifindex));
1617: break;
1618: case NEXTHOP_TYPE_IFNAME:
1619: vty_out (vty, " directly connected, %s",
1620: nexthop->ifname);
1621: break;
1622: default:
1623: break;
1624: }
1625: if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1626: vty_out (vty, " inactive");
1627:
1628: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1629: {
1630: vty_out (vty, " (recursive");
1631:
1632: switch (nexthop->rtype)
1633: {
1634: case NEXTHOP_TYPE_IPV6:
1635: case NEXTHOP_TYPE_IPV6_IFINDEX:
1636: case NEXTHOP_TYPE_IPV6_IFNAME:
1637: vty_out (vty, " via %s)",
1638: inet_ntop (AF_INET6, &nexthop->rgate.ipv6,
1639: buf, BUFSIZ));
1640: if (nexthop->rifindex)
1641: vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
1642: break;
1643: case NEXTHOP_TYPE_IFINDEX:
1644: case NEXTHOP_TYPE_IFNAME:
1645: vty_out (vty, " is directly connected, %s)",
1646: ifindex2ifname (nexthop->rifindex));
1647: break;
1648: default:
1649: break;
1650: }
1651: }
1652: vty_out (vty, "%s", VTY_NEWLINE);
1653: }
1654: vty_out (vty, "%s", VTY_NEWLINE);
1655: }
1656: }
1657:
1658: static void
1659: vty_show_ipv6_route (struct vty *vty, struct route_node *rn,
1660: struct rib *rib)
1661: {
1662: struct nexthop *nexthop;
1663: int len = 0;
1664: char buf[BUFSIZ];
1665:
1666: /* Nexthop information. */
1667: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1668: {
1669: if (nexthop == rib->nexthop)
1670: {
1671: /* Prefix information. */
1672: len = vty_out (vty, "%c%c%c %s/%d",
1673: zebra_route_char (rib->type),
1674: CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)
1675: ? '>' : ' ',
1676: CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
1677: ? '*' : ' ',
1678: inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
1679: rn->p.prefixlen);
1680:
1681: /* Distance and metric display. */
1682: if (rib->type != ZEBRA_ROUTE_CONNECT
1683: && rib->type != ZEBRA_ROUTE_KERNEL)
1684: len += vty_out (vty, " [%d/%d]", rib->distance,
1685: rib->metric);
1686: }
1687: else
1688: vty_out (vty, " %c%*c",
1689: CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
1690: ? '*' : ' ',
1691: len - 3, ' ');
1692:
1693: switch (nexthop->type)
1694: {
1695: case NEXTHOP_TYPE_IPV6:
1696: case NEXTHOP_TYPE_IPV6_IFINDEX:
1697: case NEXTHOP_TYPE_IPV6_IFNAME:
1698: vty_out (vty, " via %s",
1699: inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
1700: if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1701: vty_out (vty, ", %s", nexthop->ifname);
1702: else if (nexthop->ifindex)
1703: vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex));
1704: break;
1705: case NEXTHOP_TYPE_IFINDEX:
1706: vty_out (vty, " is directly connected, %s",
1707: ifindex2ifname (nexthop->ifindex));
1708: break;
1709: case NEXTHOP_TYPE_IFNAME:
1710: vty_out (vty, " is directly connected, %s",
1711: nexthop->ifname);
1712: break;
1713: default:
1714: break;
1715: }
1716: if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1717: vty_out (vty, " inactive");
1718:
1719: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1720: {
1721: vty_out (vty, " (recursive");
1722:
1723: switch (nexthop->rtype)
1724: {
1725: case NEXTHOP_TYPE_IPV6:
1726: case NEXTHOP_TYPE_IPV6_IFINDEX:
1727: case NEXTHOP_TYPE_IPV6_IFNAME:
1728: vty_out (vty, " via %s)",
1729: inet_ntop (AF_INET6, &nexthop->rgate.ipv6,
1730: buf, BUFSIZ));
1731: if (nexthop->rifindex)
1732: vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
1733: break;
1734: case NEXTHOP_TYPE_IFINDEX:
1735: case NEXTHOP_TYPE_IFNAME:
1736: vty_out (vty, " is directly connected, %s)",
1737: ifindex2ifname (nexthop->rifindex));
1738: break;
1739: default:
1740: break;
1741: }
1742: }
1743:
1744: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
1745: vty_out (vty, ", bh");
1746: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT))
1747: vty_out (vty, ", rej");
1748:
1749: if (rib->type == ZEBRA_ROUTE_RIPNG
1750: || rib->type == ZEBRA_ROUTE_OSPF6
1751: || rib->type == ZEBRA_ROUTE_BABEL
1752: || rib->type == ZEBRA_ROUTE_ISIS
1753: || rib->type == ZEBRA_ROUTE_BGP)
1754: {
1755: time_t uptime;
1756: struct tm *tm;
1757:
1758: uptime = time (NULL);
1759: uptime -= rib->uptime;
1760: tm = gmtime (&uptime);
1761:
1762: #define ONE_DAY_SECOND 60*60*24
1763: #define ONE_WEEK_SECOND 60*60*24*7
1764:
1765: if (uptime < ONE_DAY_SECOND)
1766: vty_out (vty, ", %02d:%02d:%02d",
1767: tm->tm_hour, tm->tm_min, tm->tm_sec);
1768: else if (uptime < ONE_WEEK_SECOND)
1769: vty_out (vty, ", %dd%02dh%02dm",
1770: tm->tm_yday, tm->tm_hour, tm->tm_min);
1771: else
1772: vty_out (vty, ", %02dw%dd%02dh",
1773: tm->tm_yday/7,
1774: tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
1775: }
1776: vty_out (vty, "%s", VTY_NEWLINE);
1777: }
1778: }
1779:
1780: DEFUN (show_ipv6_route,
1781: show_ipv6_route_cmd,
1782: "show ipv6 route",
1783: SHOW_STR
1784: IP_STR
1785: "IPv6 routing table\n")
1786: {
1787: struct route_table *table;
1788: struct route_node *rn;
1789: struct rib *rib;
1790: int first = 1;
1791:
1792: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1793: if (! table)
1794: return CMD_SUCCESS;
1795:
1796: /* Show all IPv6 route. */
1797: for (rn = route_top (table); rn; rn = route_next (rn))
1798: RNODE_FOREACH_RIB (rn, rib)
1799: {
1800: if (first)
1801: {
1802: vty_out (vty, SHOW_ROUTE_V6_HEADER);
1803: first = 0;
1804: }
1805: vty_show_ipv6_route (vty, rn, rib);
1806: }
1807: return CMD_SUCCESS;
1808: }
1809:
1810: DEFUN (show_ipv6_route_prefix_longer,
1811: show_ipv6_route_prefix_longer_cmd,
1812: "show ipv6 route X:X::X:X/M longer-prefixes",
1813: SHOW_STR
1814: IP_STR
1815: "IPv6 routing table\n"
1816: "IPv6 prefix\n"
1817: "Show route matching the specified Network/Mask pair only\n")
1818: {
1819: struct route_table *table;
1820: struct route_node *rn;
1821: struct rib *rib;
1822: struct prefix p;
1823: int ret;
1824: int first = 1;
1825:
1826: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1827: if (! table)
1828: return CMD_SUCCESS;
1829:
1830: ret = str2prefix (argv[0], &p);
1831: if (! ret)
1832: {
1833: vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
1834: return CMD_WARNING;
1835: }
1836:
1837: /* Show matched type IPv6 routes. */
1838: for (rn = route_top (table); rn; rn = route_next (rn))
1839: RNODE_FOREACH_RIB (rn, rib)
1840: if (prefix_match (&p, &rn->p))
1841: {
1842: if (first)
1843: {
1844: vty_out (vty, SHOW_ROUTE_V6_HEADER);
1845: first = 0;
1846: }
1847: vty_show_ipv6_route (vty, rn, rib);
1848: }
1849: return CMD_SUCCESS;
1850: }
1851:
1852: DEFUN (show_ipv6_route_protocol,
1853: show_ipv6_route_protocol_cmd,
1854: "show ipv6 route " QUAGGA_IP6_REDIST_STR_ZEBRA,
1855: SHOW_STR
1856: IP_STR
1857: "IP routing table\n"
1858: QUAGGA_IP6_REDIST_HELP_STR_ZEBRA)
1859: {
1860: int type;
1861: struct route_table *table;
1862: struct route_node *rn;
1863: struct rib *rib;
1864: int first = 1;
1865:
1866: type = proto_redistnum (AFI_IP6, argv[0]);
1867: if (type < 0)
1868: {
1869: vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
1870: return CMD_WARNING;
1871: }
1872:
1873: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1874: if (! table)
1875: return CMD_SUCCESS;
1876:
1877: /* Show matched type IPv6 routes. */
1878: for (rn = route_top (table); rn; rn = route_next (rn))
1879: RNODE_FOREACH_RIB (rn, rib)
1880: if (rib->type == type)
1881: {
1882: if (first)
1883: {
1884: vty_out (vty, SHOW_ROUTE_V6_HEADER);
1885: first = 0;
1886: }
1887: vty_show_ipv6_route (vty, rn, rib);
1888: }
1889: return CMD_SUCCESS;
1890: }
1891:
1892: DEFUN (show_ipv6_route_addr,
1893: show_ipv6_route_addr_cmd,
1894: "show ipv6 route X:X::X:X",
1895: SHOW_STR
1896: IP_STR
1897: "IPv6 routing table\n"
1898: "IPv6 Address\n")
1899: {
1900: int ret;
1901: struct prefix_ipv6 p;
1902: struct route_table *table;
1903: struct route_node *rn;
1904:
1905: ret = str2prefix_ipv6 (argv[0], &p);
1906: if (ret <= 0)
1907: {
1908: vty_out (vty, "Malformed IPv6 address%s", VTY_NEWLINE);
1909: return CMD_WARNING;
1910: }
1911:
1912: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1913: if (! table)
1914: return CMD_SUCCESS;
1915:
1916: rn = route_node_match (table, (struct prefix *) &p);
1917: if (! rn)
1918: {
1919: vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
1920: return CMD_WARNING;
1921: }
1922:
1923: vty_show_ipv6_route_detail (vty, rn);
1924:
1925: route_unlock_node (rn);
1926:
1927: return CMD_SUCCESS;
1928: }
1929:
1930: DEFUN (show_ipv6_route_prefix,
1931: show_ipv6_route_prefix_cmd,
1932: "show ipv6 route X:X::X:X/M",
1933: SHOW_STR
1934: IP_STR
1935: "IPv6 routing table\n"
1936: "IPv6 prefix\n")
1937: {
1938: int ret;
1939: struct prefix_ipv6 p;
1940: struct route_table *table;
1941: struct route_node *rn;
1942:
1943: ret = str2prefix_ipv6 (argv[0], &p);
1944: if (ret <= 0)
1945: {
1946: vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1947: return CMD_WARNING;
1948: }
1949:
1950: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1951: if (! table)
1952: return CMD_SUCCESS;
1953:
1954: rn = route_node_match (table, (struct prefix *) &p);
1955: if (! rn || rn->p.prefixlen != p.prefixlen)
1956: {
1957: vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
1958: return CMD_WARNING;
1959: }
1960:
1961: vty_show_ipv6_route_detail (vty, rn);
1962:
1963: route_unlock_node (rn);
1964:
1965: return CMD_SUCCESS;
1966: }
1967:
1968: /* Show route summary. */
1969: DEFUN (show_ipv6_route_summary,
1970: show_ipv6_route_summary_cmd,
1971: "show ipv6 route summary",
1972: SHOW_STR
1973: IP_STR
1974: "IPv6 routing table\n"
1975: "Summary of all IPv6 routes\n")
1976: {
1977: struct route_table *table;
1978:
1979: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1980: if (! table)
1981: return CMD_SUCCESS;
1982:
1983: vty_show_ip_route_summary (vty, table);
1984:
1985: return CMD_SUCCESS;
1986: }
1987:
1988: /*
1989: * Show IPv6 mroute command.Used to dump
1990: * the Multicast routing table.
1991: */
1992:
1993: DEFUN (show_ipv6_mroute,
1994: show_ipv6_mroute_cmd,
1995: "show ipv6 mroute",
1996: SHOW_STR
1997: IP_STR
1998: "IPv6 Multicast routing table\n")
1999: {
2000: struct route_table *table;
2001: struct route_node *rn;
2002: struct rib *rib;
2003: int first = 1;
2004:
2005: table = vrf_table (AFI_IP6, SAFI_MULTICAST, 0);
2006: if (! table)
2007: return CMD_SUCCESS;
2008:
2009: /* Show all IPv6 route. */
2010: for (rn = route_top (table); rn; rn = route_next (rn))
2011: RNODE_FOREACH_RIB (rn, rib)
2012: {
2013: if (first)
2014: {
2015: vty_out (vty, SHOW_ROUTE_V6_HEADER);
2016: first = 0;
2017: }
2018: vty_show_ipv6_route (vty, rn, rib);
2019: }
2020: return CMD_SUCCESS;
2021: }
2022:
2023: /* Write IPv6 static route configuration. */
2024: static int
2025: static_config_ipv6 (struct vty *vty)
2026: {
2027: struct route_node *rn;
2028: struct static_ipv6 *si;
2029: int write;
2030: char buf[BUFSIZ];
2031: struct route_table *stable;
2032:
2033: write = 0;
2034:
2035: /* Lookup table. */
2036: stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, 0);
2037: if (! stable)
2038: return -1;
2039:
2040: for (rn = route_top (stable); rn; rn = route_next (rn))
2041: for (si = rn->info; si; si = si->next)
2042: {
2043: vty_out (vty, "ipv6 route %s/%d",
2044: inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
2045: rn->p.prefixlen);
2046:
2047: switch (si->type)
2048: {
2049: case STATIC_IPV6_GATEWAY:
2050: vty_out (vty, " %s", inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ));
2051: break;
2052: case STATIC_IPV6_IFNAME:
2053: vty_out (vty, " %s", si->ifname);
2054: break;
2055: case STATIC_IPV6_GATEWAY_IFNAME:
2056: vty_out (vty, " %s %s",
2057: inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ), si->ifname);
2058: break;
2059: }
2060:
2061: if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT))
2062: vty_out (vty, " %s", "reject");
2063:
2064: if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE))
2065: vty_out (vty, " %s", "blackhole");
2066:
2067: if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
2068: vty_out (vty, " %d", si->distance);
2069: vty_out (vty, "%s", VTY_NEWLINE);
2070:
2071: write = 1;
2072: }
2073: return write;
2074: }
2075: #endif /* HAVE_IPV6 */
2076:
2077: /* Static ip route configuration write function. */
2078: static int
2079: zebra_ip_config (struct vty *vty)
2080: {
2081: int write = 0;
2082:
2083: write += static_config_ipv4 (vty);
2084: #ifdef HAVE_IPV6
2085: write += static_config_ipv6 (vty);
2086: #endif /* HAVE_IPV6 */
2087:
2088: return write;
2089: }
2090:
2091: /* ip protocol configuration write function */
2092: static int config_write_protocol(struct vty *vty)
2093: {
2094: int i;
2095:
2096: for (i=0;i<ZEBRA_ROUTE_MAX;i++)
2097: {
2098: if (proto_rm[AFI_IP][i])
2099: vty_out (vty, "ip protocol %s route-map %s%s", zebra_route_string(i),
2100: proto_rm[AFI_IP][i], VTY_NEWLINE);
2101: }
2102: if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX])
2103: vty_out (vty, "ip protocol %s route-map %s%s", "any",
2104: proto_rm[AFI_IP][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
2105:
2106: return 1;
2107: }
2108:
2109: /* table node for protocol filtering */
2110: static struct cmd_node protocol_node = { PROTOCOL_NODE, "", 1 };
2111:
2112: /* IP node for static routes. */
2113: static struct cmd_node ip_node = { IP_NODE, "", 1 };
2114:
2115: /* Route VTY. */
2116: void
2117: zebra_vty_init (void)
2118: {
2119: install_node (&ip_node, zebra_ip_config);
2120: install_node (&protocol_node, config_write_protocol);
2121:
2122: install_element (CONFIG_NODE, &ip_protocol_cmd);
2123: install_element (CONFIG_NODE, &no_ip_protocol_cmd);
2124: install_element (VIEW_NODE, &show_ip_protocol_cmd);
2125: install_element (ENABLE_NODE, &show_ip_protocol_cmd);
2126: install_element (CONFIG_NODE, &ip_route_cmd);
2127: install_element (CONFIG_NODE, &ip_route_flags_cmd);
2128: install_element (CONFIG_NODE, &ip_route_flags2_cmd);
2129: install_element (CONFIG_NODE, &ip_route_mask_cmd);
2130: install_element (CONFIG_NODE, &ip_route_mask_flags_cmd);
2131: install_element (CONFIG_NODE, &ip_route_mask_flags2_cmd);
2132: install_element (CONFIG_NODE, &no_ip_route_cmd);
2133: install_element (CONFIG_NODE, &no_ip_route_flags_cmd);
2134: install_element (CONFIG_NODE, &no_ip_route_flags2_cmd);
2135: install_element (CONFIG_NODE, &no_ip_route_mask_cmd);
2136: install_element (CONFIG_NODE, &no_ip_route_mask_flags_cmd);
2137: install_element (CONFIG_NODE, &no_ip_route_mask_flags2_cmd);
2138: install_element (CONFIG_NODE, &ip_route_distance_cmd);
2139: install_element (CONFIG_NODE, &ip_route_flags_distance_cmd);
2140: install_element (CONFIG_NODE, &ip_route_flags_distance2_cmd);
2141: install_element (CONFIG_NODE, &ip_route_mask_distance_cmd);
2142: install_element (CONFIG_NODE, &ip_route_mask_flags_distance_cmd);
2143: install_element (CONFIG_NODE, &ip_route_mask_flags_distance2_cmd);
2144: install_element (CONFIG_NODE, &no_ip_route_distance_cmd);
2145: install_element (CONFIG_NODE, &no_ip_route_flags_distance_cmd);
2146: install_element (CONFIG_NODE, &no_ip_route_flags_distance2_cmd);
2147: install_element (CONFIG_NODE, &no_ip_route_mask_flags_distance_cmd);
2148: install_element (CONFIG_NODE, &no_ip_route_mask_flags_distance2_cmd);
2149:
2150: install_element (VIEW_NODE, &show_ip_route_cmd);
2151: install_element (VIEW_NODE, &show_ip_route_addr_cmd);
2152: install_element (VIEW_NODE, &show_ip_route_prefix_cmd);
2153: install_element (VIEW_NODE, &show_ip_route_prefix_longer_cmd);
2154: install_element (VIEW_NODE, &show_ip_route_protocol_cmd);
2155: install_element (VIEW_NODE, &show_ip_route_supernets_cmd);
2156: install_element (VIEW_NODE, &show_ip_route_summary_cmd);
2157: install_element (ENABLE_NODE, &show_ip_route_cmd);
2158: install_element (ENABLE_NODE, &show_ip_route_addr_cmd);
2159: install_element (ENABLE_NODE, &show_ip_route_prefix_cmd);
2160: install_element (ENABLE_NODE, &show_ip_route_prefix_longer_cmd);
2161: install_element (ENABLE_NODE, &show_ip_route_protocol_cmd);
2162: install_element (ENABLE_NODE, &show_ip_route_supernets_cmd);
2163: install_element (ENABLE_NODE, &show_ip_route_summary_cmd);
2164:
2165: install_element (VIEW_NODE, &show_ip_mroute_cmd);
2166: install_element (ENABLE_NODE, &show_ip_mroute_cmd);
2167:
2168:
2169: #ifdef HAVE_IPV6
2170: install_element (CONFIG_NODE, &ipv6_route_cmd);
2171: install_element (CONFIG_NODE, &ipv6_route_flags_cmd);
2172: install_element (CONFIG_NODE, &ipv6_route_ifname_cmd);
2173: install_element (CONFIG_NODE, &ipv6_route_ifname_flags_cmd);
2174: install_element (CONFIG_NODE, &no_ipv6_route_cmd);
2175: install_element (CONFIG_NODE, &no_ipv6_route_flags_cmd);
2176: install_element (CONFIG_NODE, &no_ipv6_route_ifname_cmd);
2177: install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_cmd);
2178: install_element (CONFIG_NODE, &ipv6_route_pref_cmd);
2179: install_element (CONFIG_NODE, &ipv6_route_flags_pref_cmd);
2180: install_element (CONFIG_NODE, &ipv6_route_ifname_pref_cmd);
2181: install_element (CONFIG_NODE, &ipv6_route_ifname_flags_pref_cmd);
2182: install_element (CONFIG_NODE, &no_ipv6_route_pref_cmd);
2183: install_element (CONFIG_NODE, &no_ipv6_route_flags_pref_cmd);
2184: install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_cmd);
2185: install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_pref_cmd);
2186: install_element (VIEW_NODE, &show_ipv6_route_cmd);
2187: install_element (VIEW_NODE, &show_ipv6_route_summary_cmd);
2188: install_element (VIEW_NODE, &show_ipv6_route_protocol_cmd);
2189: install_element (VIEW_NODE, &show_ipv6_route_addr_cmd);
2190: install_element (VIEW_NODE, &show_ipv6_route_prefix_cmd);
2191: install_element (VIEW_NODE, &show_ipv6_route_prefix_longer_cmd);
2192: install_element (ENABLE_NODE, &show_ipv6_route_cmd);
2193: install_element (ENABLE_NODE, &show_ipv6_route_protocol_cmd);
2194: install_element (ENABLE_NODE, &show_ipv6_route_addr_cmd);
2195: install_element (ENABLE_NODE, &show_ipv6_route_prefix_cmd);
2196: install_element (ENABLE_NODE, &show_ipv6_route_prefix_longer_cmd);
2197: install_element (ENABLE_NODE, &show_ipv6_route_summary_cmd);
2198:
2199: install_element (VIEW_NODE, &show_ipv6_mroute_cmd);
2200: install_element (ENABLE_NODE, &show_ipv6_mroute_cmd);
2201: #endif /* HAVE_IPV6 */
2202: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>