blob: 39a7690b1b60c3c7eb6b2c9ff319049cdc8404a6 [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/* Routing Information Base.
2 * Copyright (C) 1997, 98, 99, 2001 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 Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "prefix.h"
25#include "table.h"
26#include "memory.h"
27#include "vty.h"
28#include "str.h"
29#include "command.h"
30#include "linklist.h"
31#include "if.h"
32#include "log.h"
33#include "sockunion.h"
34
35#include "zebra/rib.h"
36#include "zebra/rt.h"
37#include "zebra/zserv.h"
38#include "zebra/redistribute.h"
39#include "zebra/debug.h"
40
41/* Routing information base and static table for IPv4. */
42struct route_table *rib_table_ipv4;
43struct route_table *static_table_ipv4;
44
45/* Routing information base and static table for IPv6. */
46#ifdef HAVE_IPV6
47struct route_table *rib_table_ipv6;
48struct route_table *static_table_ipv6;
49#endif /* HAVE_IPV6 */
50
51/* Default rtm_table for all clients */
52extern int rtm_table_default;
53
54/* Each route type's string and default distance value. */
55struct
56{
57 int key;
58 char c;
59 char *str;
60 int distance;
61} route_info[] =
62{
63 {ZEBRA_ROUTE_SYSTEM, 'X', "system", 0},
64 {ZEBRA_ROUTE_KERNEL, 'K', "kernel", 0},
65 {ZEBRA_ROUTE_CONNECT, 'C', "connected", 0},
66 {ZEBRA_ROUTE_STATIC, 'S', "static", 1},
67 {ZEBRA_ROUTE_RIP, 'R', "rip", 120},
68 {ZEBRA_ROUTE_RIPNG, 'R', "ripng", 120},
69 {ZEBRA_ROUTE_OSPF, 'O', "ospf", 110},
70 {ZEBRA_ROUTE_OSPF6, 'O', "ospf6", 110},
71 {ZEBRA_ROUTE_ISIS, 'I', "isis", 115},
72 {ZEBRA_ROUTE_BGP, 'B', "bgp", 20 /* IBGP is 200. */}
73};
74
75/* Add nexthop to the end of the list. */
76void
77nexthop_add (struct rib *rib, struct nexthop *nexthop)
78{
79 struct nexthop *last;
80
81 for (last = rib->nexthop; last && last->next; last = last->next)
82 ;
83 if (last)
84 last->next = nexthop;
85 else
86 rib->nexthop = nexthop;
87 nexthop->prev = last;
88
89 rib->nexthop_num++;
90}
91
92/* Delete specified nexthop from the list. */
93void
94nexthop_delete (struct rib *rib, struct nexthop *nexthop)
95{
96 if (nexthop->next)
97 nexthop->next->prev = nexthop->prev;
98 if (nexthop->prev)
99 nexthop->prev->next = nexthop->next;
100 else
101 rib->nexthop = nexthop->next;
102 rib->nexthop_num--;
103}
104
105/* Free nexthop. */
106void
107nexthop_free (struct nexthop *nexthop)
108{
109 if (nexthop->type == NEXTHOP_TYPE_IFNAME && nexthop->ifname)
110 free (nexthop->ifname);
111 XFREE (MTYPE_NEXTHOP, nexthop);
112}
113
114struct nexthop *
115nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
116{
117 struct nexthop *nexthop;
118
119 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
120 memset (nexthop, 0, sizeof (struct nexthop));
121 nexthop->type = NEXTHOP_TYPE_IFINDEX;
122 nexthop->ifindex = ifindex;
123
124 nexthop_add (rib, nexthop);
125
126 return nexthop;
127}
128
129struct nexthop *
130nexthop_ifname_add (struct rib *rib, char *ifname)
131{
132 struct nexthop *nexthop;
133
134 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
135 memset (nexthop, 0, sizeof (struct nexthop));
136 nexthop->type = NEXTHOP_TYPE_IFNAME;
137 nexthop->ifname = strdup (ifname);
138
139 nexthop_add (rib, nexthop);
140
141 return nexthop;
142}
143
144struct nexthop *
145nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4)
146{
147 struct nexthop *nexthop;
148
149 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
150 memset (nexthop, 0, sizeof (struct nexthop));
151 nexthop->type = NEXTHOP_TYPE_IPV4;
152 nexthop->gate.ipv4 = *ipv4;
153
154 nexthop_add (rib, nexthop);
155
156 return nexthop;
157}
158
159struct nexthop *
160nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
161 unsigned int ifindex)
162{
163 struct nexthop *nexthop;
164
165 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
166 memset (nexthop, 0, sizeof (struct nexthop));
167 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
168 nexthop->gate.ipv4 = *ipv4;
169 nexthop->ifindex = ifindex;
170
171 nexthop_add (rib, nexthop);
172
173 return nexthop;
174}
175
176#ifdef HAVE_IPV6
177struct nexthop *
178nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
179{
180 struct nexthop *nexthop;
181
182 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
183 memset (nexthop, 0, sizeof (struct nexthop));
184 nexthop->type = NEXTHOP_TYPE_IPV6;
185 nexthop->gate.ipv6 = *ipv6;
186
187 nexthop_add (rib, nexthop);
188
189 return nexthop;
190}
191
192struct nexthop *
193nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
194 char *ifname)
195{
196 struct nexthop *nexthop;
197
198 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
199 memset (nexthop, 0, sizeof (struct nexthop));
200 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
201 nexthop->gate.ipv6 = *ipv6;
202 nexthop->ifname = XSTRDUP (0, ifname);
203
204 nexthop_add (rib, nexthop);
205
206 return nexthop;
207}
208
209struct nexthop *
210nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
211 unsigned int ifindex)
212{
213 struct nexthop *nexthop;
214
215 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
216 memset (nexthop, 0, sizeof (struct nexthop));
217 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
218 nexthop->gate.ipv6 = *ipv6;
219 nexthop->ifindex = ifindex;
220
221 nexthop_add (rib, nexthop);
222
223 return nexthop;
224}
225#endif /* HAVE_IPV6 */
226
227/* If force flag is not set, do not modify falgs at all for uninstall
228 the route from FIB. */
229int
230nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
231 struct route_node *top)
232{
233 struct prefix_ipv4 p;
234 struct route_node *rn;
235 struct rib *match;
236 struct nexthop *newhop;
237
238 if (nexthop->type == NEXTHOP_TYPE_IPV4)
239 nexthop->ifindex = 0;
240
241 if (set)
242 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
243
244 /* Make lookup prefix. */
245 memset (&p, 0, sizeof (struct prefix_ipv4));
246 p.family = AF_INET;
247 p.prefixlen = IPV4_MAX_PREFIXLEN;
248 p.prefix = nexthop->gate.ipv4;
249
250 rn = route_node_match (rib_table_ipv4, (struct prefix *) &p);
251 while (rn)
252 {
253 route_unlock_node (rn);
254
255 /* If lookup self prefix return immidiately. */
256 if (rn == top)
257 return 0;
258
259 /* Pick up selected route. */
260 for (match = rn->info; match; match = match->next)
261 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
262 break;
263
264 /* If there is no selected route or matched route is EGP, go up
265 tree. */
266 if (! match
267 || match->type == ZEBRA_ROUTE_BGP)
268 {
269 do {
270 rn = rn->parent;
271 } while (rn && rn->info == NULL);
272 if (rn)
273 route_lock_node (rn);
274 }
275 else
276 {
277 if (match->type == ZEBRA_ROUTE_CONNECT)
278 {
279 /* Directly point connected route. */
280 newhop = match->nexthop;
281 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
282 nexthop->ifindex = newhop->ifindex;
283
284 return 1;
285 }
286 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
287 {
288 for (newhop = match->nexthop; newhop; newhop = newhop->next)
289 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
290 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
291 {
292 if (set)
293 {
294 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
295 nexthop->rtype = newhop->type;
296 if (newhop->type == NEXTHOP_TYPE_IPV4 ||
297 newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
298 nexthop->rgate.ipv4 = newhop->gate.ipv4;
299 if (newhop->type == NEXTHOP_TYPE_IFINDEX
300 || newhop->type == NEXTHOP_TYPE_IFNAME
301 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
302 nexthop->rifindex = newhop->ifindex;
303 }
304 return 1;
305 }
306 return 0;
307 }
308 else
309 {
310 return 0;
311 }
312 }
313 }
314 return 0;
315}
316
317#ifdef HAVE_IPV6
318/* If force flag is not set, do not modify falgs at all for uninstall
319 the route from FIB. */
320int
321nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
322 struct route_node *top)
323{
324 struct prefix_ipv6 p;
325 struct route_node *rn;
326 struct rib *match;
327 struct nexthop *newhop;
328
329 if (nexthop->type == NEXTHOP_TYPE_IPV6)
330 nexthop->ifindex = 0;
331
332 if (set)
333 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
334
335 /* Make lookup prefix. */
336 memset (&p, 0, sizeof (struct prefix_ipv6));
337 p.family = AF_INET6;
338 p.prefixlen = IPV6_MAX_PREFIXLEN;
339 p.prefix = nexthop->gate.ipv6;
340
341 rn = route_node_match (rib_table_ipv6, (struct prefix *) &p);
342 while (rn)
343 {
344 route_unlock_node (rn);
345
346 /* If lookup self prefix return immidiately. */
347 if (rn == top)
348 return 0;
349
350 /* Pick up selected route. */
351 for (match = rn->info; match; match = match->next)
352 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
353 break;
354
355 /* If there is no selected route or matched route is EGP, go up
356 tree. */
357 if (! match
358 || match->type == ZEBRA_ROUTE_BGP)
359 {
360 do {
361 rn = rn->parent;
362 } while (rn && rn->info == NULL);
363 if (rn)
364 route_lock_node (rn);
365 }
366 else
367 {
368 if (match->type == ZEBRA_ROUTE_CONNECT)
369 {
370 /* Directly point connected route. */
371 newhop = match->nexthop;
372
373 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
374 nexthop->ifindex = newhop->ifindex;
375
376 return 1;
377 }
378 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
379 {
380 for (newhop = match->nexthop; newhop; newhop = newhop->next)
381 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
382 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
383 {
384 if (set)
385 {
386 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
387 nexthop->rtype = newhop->type;
388 if (newhop->type == NEXTHOP_TYPE_IPV6
389 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
390 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
391 nexthop->rgate.ipv6 = newhop->gate.ipv6;
392 if (newhop->type == NEXTHOP_TYPE_IFINDEX
393 || newhop->type == NEXTHOP_TYPE_IFNAME
394 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
395 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
396 nexthop->rifindex = newhop->ifindex;
397 }
398 return 1;
399 }
400 return 0;
401 }
402 else
403 {
404 return 0;
405 }
406 }
407 }
408 return 0;
409}
410#endif /* HAVE_IPV6 */
411
412struct rib *
413rib_match_ipv4 (struct in_addr addr)
414{
415 struct prefix_ipv4 p;
416 struct route_node *rn;
417 struct rib *match;
418 struct nexthop *newhop;
419
420 memset (&p, 0, sizeof (struct prefix_ipv4));
421 p.family = AF_INET;
422 p.prefixlen = IPV4_MAX_PREFIXLEN;
423 p.prefix = addr;
424
425 rn = route_node_match (rib_table_ipv4, (struct prefix *) &p);
426
427 while (rn)
428 {
429 route_unlock_node (rn);
430
431 /* Pick up selected route. */
432 for (match = rn->info; match; match = match->next)
433 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
434 break;
435
436 /* If there is no selected route or matched route is EGP, go up
437 tree. */
438 if (! match
439 || match->type == ZEBRA_ROUTE_BGP)
440 {
441 do {
442 rn = rn->parent;
443 } while (rn && rn->info == NULL);
444 if (rn)
445 route_lock_node (rn);
446 }
447 else
448 {
449 if (match->type == ZEBRA_ROUTE_CONNECT)
450 /* Directly point connected route. */
451 return match;
452 else
453 {
454 for (newhop = match->nexthop; newhop; newhop = newhop->next)
455 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
456 return match;
457 return NULL;
458 }
459 }
460 }
461 return NULL;
462}
463
464struct rib *
465rib_lookup_ipv4 (struct prefix_ipv4 *p)
466{
467 struct route_node *rn;
468 struct rib *match;
469 struct nexthop *nexthop;
470
471 rn = route_node_lookup (rib_table_ipv4, (struct prefix *) p);
472
473 /* No route for this prefix. */
474 if (! rn)
475 return NULL;
476
477 /* Unlock node. */
478 route_unlock_node (rn);
479
480 /* Pick up selected route. */
481 for (match = rn->info; match; match = match->next)
482 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
483 break;
484
485 if (! match || match->type == ZEBRA_ROUTE_BGP)
486 return NULL;
487
488 if (match->type == ZEBRA_ROUTE_CONNECT)
489 return match;
490
491 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
492 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
493 return match;
494
495 return NULL;
496}
497
498#ifdef HAVE_IPV6
499struct rib *
500rib_match_ipv6 (struct in6_addr *addr)
501{
502 struct prefix_ipv6 p;
503 struct route_node *rn;
504 struct rib *match;
505 struct nexthop *newhop;
506
507 memset (&p, 0, sizeof (struct prefix_ipv6));
508 p.family = AF_INET6;
509 p.prefixlen = IPV6_MAX_PREFIXLEN;
510 IPV6_ADDR_COPY (&p.prefix, addr);
511
512 rn = route_node_match (rib_table_ipv6, (struct prefix *) &p);
513
514 while (rn)
515 {
516 route_unlock_node (rn);
517
518 /* Pick up selected route. */
519 for (match = rn->info; match; match = match->next)
520 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
521 break;
522
523 /* If there is no selected route or matched route is EGP, go up
524 tree. */
525 if (! match
526 || match->type == ZEBRA_ROUTE_BGP)
527 {
528 do {
529 rn = rn->parent;
530 } while (rn && rn->info == NULL);
531 if (rn)
532 route_lock_node (rn);
533 }
534 else
535 {
536 if (match->type == ZEBRA_ROUTE_CONNECT)
537 /* Directly point connected route. */
538 return match;
539 else
540 {
541 for (newhop = match->nexthop; newhop; newhop = newhop->next)
542 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
543 return match;
544 return NULL;
545 }
546 }
547 }
548 return NULL;
549}
550#endif /* HAVE_IPV6 */
551
552int
553nexthop_active_check (struct route_node *rn, struct rib *rib,
554 struct nexthop *nexthop, int set)
555{
556 struct interface *ifp;
557
558 switch (nexthop->type)
559 {
560 case NEXTHOP_TYPE_IFINDEX:
561 ifp = if_lookup_by_index (nexthop->ifindex);
562 if (ifp && if_is_up (ifp))
563 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
564 else
565 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
566 break;
567 case NEXTHOP_TYPE_IFNAME:
568 case NEXTHOP_TYPE_IPV6_IFNAME:
569 ifp = if_lookup_by_name (nexthop->ifname);
570 if (ifp && if_is_up (ifp))
571 {
572 if (set)
573 nexthop->ifindex = ifp->ifindex;
574 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
575 }
576 else
577 {
578 if (set)
579 nexthop->ifindex = 0;
580 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
581 }
582 break;
583 case NEXTHOP_TYPE_IPV4:
584 case NEXTHOP_TYPE_IPV4_IFINDEX:
585 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
586 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
587 else
588 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
589 break;
590#ifdef HAVE_IPV6
591 case NEXTHOP_TYPE_IPV6:
592 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
593 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
594 else
595 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
596 break;
597 case NEXTHOP_TYPE_IPV6_IFINDEX:
598 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
599 {
600 ifp = if_lookup_by_index (nexthop->ifindex);
601 if (ifp && if_is_up (ifp))
602 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
603 else
604 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
605 }
606 else
607 {
608 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
609 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
610 else
611 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
612 }
613 break;
614#endif /* HAVE_IPV6 */
615 default:
616 break;
617 }
618 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
619}
620
621int
622nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
623{
624 struct nexthop *nexthop;
625 int active;
626
627 rib->nexthop_active_num = 0;
628 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
629
630 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
631 {
632 active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
633 rib->nexthop_active_num += nexthop_active_check (rn, rib, nexthop, set);
634 if (active != CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
635 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
636 }
637 return rib->nexthop_active_num;
638}
639
640#define RIB_SYSTEM_ROUTE(R) \
641 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
642
643void
644newrib_free (struct rib *rib)
645{
646 struct nexthop *nexthop;
647 struct nexthop *next;
648
649 for (nexthop = rib->nexthop; nexthop; nexthop = next)
650 {
651 next = nexthop->next;
652 nexthop_free (nexthop);
653 }
654 XFREE (MTYPE_RIB, rib);
655}
656
657void
658rib_install_kernel (struct route_node *rn, struct rib *rib)
659{
660 int ret = 0;
661 struct nexthop *nexthop;
662
663 switch (PREFIX_FAMILY (&rn->p))
664 {
665 case AF_INET:
666 ret = kernel_add_ipv4 (&rn->p, rib);
667 break;
668#ifdef HAVE_IPV6
669 case AF_INET6:
670 ret = kernel_add_ipv6 (&rn->p, rib);
671 break;
672#endif /* HAVE_IPV6 */
673 }
674
675 if (ret < 0)
676 {
677 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
678 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
679 }
680}
681
682/* Uninstall the route from kernel. */
683int
684rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
685{
686 int ret = 0;
687 struct nexthop *nexthop;
688
689 switch (PREFIX_FAMILY (&rn->p))
690 {
691 case AF_INET:
692 ret = kernel_delete_ipv4 (&rn->p, rib);
693 break;
694#ifdef HAVE_IPV6
695 case AF_INET6:
696 ret = kernel_delete_ipv6 (&rn->p, rib);
697 break;
698#endif /* HAVE_IPV6 */
699 }
700
701 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
702 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
703
704 return ret;
705}
706
707/* Uninstall the route from kernel. */
708void
709rib_uninstall (struct route_node *rn, struct rib *rib)
710{
711 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
712 {
713 redistribute_delete (&rn->p, rib);
714 if (! RIB_SYSTEM_ROUTE (rib))
715 rib_uninstall_kernel (rn, rib);
716 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
717 }
718}
719
720/* Core function for processing routing information base. */
721void
722rib_process (struct route_node *rn, struct rib *del)
723{
724 struct rib *rib;
725 struct rib *next;
726 struct rib *fib = NULL;
727 struct rib *select = NULL;
728
729 for (rib = rn->info; rib; rib = next)
730 {
731 next = rib->next;
732
733 /* Currently installed rib. */
734 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
735 fib = rib;
736
737 /* Skip unreachable nexthop. */
738 if (! nexthop_active_update (rn, rib, 0))
739 continue;
740
741 /* Infinit distance. */
742 if (rib->distance == DISTANCE_INFINITY)
743 continue;
744
745 /* Newly selected rib. */
746 if (! select || rib->distance < select->distance
747 || rib->type == ZEBRA_ROUTE_CONNECT)
748 select = rib;
749 }
750
751 /* Deleted route check. */
752 if (del && CHECK_FLAG (del->flags, ZEBRA_FLAG_SELECTED))
753 fib = del;
754
755 /* Same route is selected. */
756 if (select && select == fib)
757 {
758 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
759 {
760 redistribute_delete (&rn->p, select);
761 if (! RIB_SYSTEM_ROUTE (select))
762 rib_uninstall_kernel (rn, select);
763
764 /* Set real nexthop. */
765 nexthop_active_update (rn, select, 1);
766
767 if (! RIB_SYSTEM_ROUTE (select))
768 rib_install_kernel (rn, select);
769 redistribute_add (&rn->p, select);
770 }
771 return;
772 }
773
774 /* Uninstall old rib from forwarding table. */
775 if (fib)
776 {
777 redistribute_delete (&rn->p, fib);
778 if (! RIB_SYSTEM_ROUTE (fib))
779 rib_uninstall_kernel (rn, fib);
780 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
781
782 /* Set real nexthop. */
783 nexthop_active_update (rn, fib, 1);
784 }
785
786 /* Install new rib into forwarding table. */
787 if (select)
788 {
789 /* Set real nexthop. */
790 nexthop_active_update (rn, select, 1);
791
792 if (! RIB_SYSTEM_ROUTE (select))
793 rib_install_kernel (rn, select);
794 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
795 redistribute_add (&rn->p, select);
796 }
797}
798
799/* Add RIB to head of the route node. */
800void
801rib_addnode (struct route_node *rn, struct rib *rib)
802{
803 struct rib *head;
804
805 head = rn->info;
806 if (head)
807 head->prev = rib;
808 rib->next = head;
809 rn->info = rib;
810}
811
812void
813rib_delnode (struct route_node *rn, struct rib *rib)
814{
815 if (rib->next)
816 rib->next->prev = rib->prev;
817 if (rib->prev)
818 rib->prev->next = rib->next;
819 else
820 rn->info = rib->next;
821}
822
823int
824rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
825 struct in_addr *gate, unsigned int ifindex, int table,
826 u_int32_t metric, u_char distance)
827{
828 struct rib *rib;
829 struct rib *same = NULL;
830 struct route_node *rn;
831 struct nexthop *nexthop;
832
833 /* Make it sure prefixlen is applied to the prefix. */
834 apply_mask_ipv4 (p);
835
836 /* Set default distance by route type. */
837 if (distance == 0)
838 {
839 distance = route_info[type].distance;
840
841 /* iBGP distance is 200. */
842 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
843 distance = 200;
844 }
845
846 /* Lookup route node.*/
847 rn = route_node_get (rib_table_ipv4, (struct prefix *) p);
848
849 /* If same type of route are installed, treat it as a implicit
850 withdraw. */
851 for (rib = rn->info; rib; rib = rib->next)
852 {
853 if (rib->type == ZEBRA_ROUTE_CONNECT)
854 {
855 nexthop = rib->nexthop;
856
857 /* Duplicate connected route comes in. */
858 if (rib->type == type
859 && (! table || rib->table == table)
860 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
861 && nexthop->ifindex == ifindex)
862 {
863 rib->refcnt++;
864 return 0 ;
865 }
866 }
867 else if (rib->type == type
868 && (! table || rib->table == table))
869 {
870 same = rib;
871 rib_delnode (rn, same);
872 route_unlock_node (rn);
873 break;
874 }
875 }
876
877 /* Allocate new rib structure. */
878 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
879 memset (rib, 0, sizeof (struct rib));
880 rib->type = type;
881 rib->distance = distance;
882 rib->flags = flags;
883 rib->metric = metric;
884 rib->table = table;
885 rib->nexthop_num = 0;
886 rib->uptime = time (NULL);
887
888 /* Nexthop settings. */
889 if (gate)
890 {
891 if (ifindex)
892 nexthop_ipv4_ifindex_add (rib, gate, ifindex);
893 else
894 nexthop_ipv4_add (rib, gate);
895 }
896 else
897 nexthop_ifindex_add (rib, ifindex);
898
899 /* If this route is kernel route, set FIB flag to the route. */
900 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
901 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
902 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
903
904 /* Link new rib to node.*/
905 rib_addnode (rn, rib);
906
907 /* Process this route node. */
908 rib_process (rn, same);
909
910 /* Free implicit route.*/
911 if (same)
912 newrib_free (same);
913
914 return 0;
915}
916
917int
918rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
919{
920 struct route_node *rn;
921 struct rib *same;
922 struct nexthop *nexthop;
923
924 /* Make it sure prefixlen is applied to the prefix. */
925 apply_mask_ipv4 (p);
926
927 /* Set default distance by route type. */
928 if (rib->distance == 0)
929 {
930 rib->distance = route_info[rib->type].distance;
931
932 /* iBGP distance is 200. */
933 if (rib->type == ZEBRA_ROUTE_BGP
934 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
935 rib->distance = 200;
936 }
937
938 /* Lookup route node.*/
939 rn = route_node_get (rib_table_ipv4, (struct prefix *) p);
940
941 /* If same type of route are installed, treat it as a implicit
942 withdraw. */
943 for (same = rn->info; same; same = same->next)
944 {
945 if (same->type == rib->type && same->table == rib->table
946 && same->type != ZEBRA_ROUTE_CONNECT)
947 {
948 rib_delnode (rn, same);
949 route_unlock_node (rn);
950 break;
951 }
952 }
953
954 /* If this route is kernel route, set FIB flag to the route. */
955 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
956 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
957 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
958
959 /* Link new rib to node.*/
960 rib_addnode (rn, rib);
961
962 /* Process this route node. */
963 rib_process (rn, same);
964
965 /* Free implicit route.*/
966 if (same)
967 newrib_free (same);
968
969 return 0;
970}
971
972int
973rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
974 struct in_addr *gate, unsigned int ifindex, int table)
975{
976 struct route_node *rn;
977 struct rib *rib;
978 struct rib *fib = NULL;
979 struct rib *same = NULL;
980 struct nexthop *nexthop;
981 char buf1[BUFSIZ];
982 char buf2[BUFSIZ];
983
984 /* Apply mask. */
985 apply_mask_ipv4 (p);
986
987 /* Lookup route node. */
988 rn = route_node_lookup (rib_table_ipv4, (struct prefix *) p);
989 if (! rn)
990 {
991 if (IS_ZEBRA_DEBUG_KERNEL)
992 {
993 if (gate)
994 zlog_info ("route %s/%d via %s ifindex %d doesn't exist in rib",
995 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
996 p->prefixlen,
997 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
998 ifindex);
999 else
1000 zlog_info ("route %s/%d ifindex %d doesn't exist in rib",
1001 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1002 p->prefixlen,
1003 ifindex);
1004 }
1005 return ZEBRA_ERR_RTNOEXIST;
1006 }
1007
1008 /* Lookup same type route. */
1009 for (rib = rn->info; rib; rib = rib->next)
1010 {
1011 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1012 fib = rib;
1013
1014 if (rib->type == ZEBRA_ROUTE_CONNECT)
1015 {
1016 nexthop = rib->nexthop;
1017
1018 if (rib->type == type
1019 && (! table || rib->table == table)
1020 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
1021 && nexthop->ifindex == ifindex)
1022 {
1023 if (rib->refcnt)
1024 {
1025 rib->refcnt--;
1026 route_unlock_node (rn);
1027 route_unlock_node (rn);
1028 return 0;
1029 }
1030 same = rib;
1031 break;
1032 }
1033 }
1034 else
1035 {
1036 if (rib->type == type
1037 && (!table || rib->table == table))
1038 {
1039 same = rib;
1040 break;
1041 }
1042 }
1043 }
1044
1045 /* If same type of route can't be found and this message is from
1046 kernel. */
1047 if (! same)
1048 {
1049 if (fib && type == ZEBRA_ROUTE_KERNEL)
1050 {
1051 /* Unset flags. */
1052 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1053 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1054
1055 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1056 }
1057 else
1058 {
1059 if (IS_ZEBRA_DEBUG_KERNEL)
1060 {
1061 if (gate)
1062 zlog_info ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
1063 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1064 p->prefixlen,
1065 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1066 ifindex,
1067 type);
1068 else
1069 zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib",
1070 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1071 p->prefixlen,
1072 ifindex,
1073 type);
1074 }
1075 route_unlock_node (rn);
1076 return ZEBRA_ERR_RTNOEXIST;
1077 }
1078 }
1079
1080 if (same)
1081 rib_delnode (rn, same);
1082
1083 /* Process changes. */
1084 rib_process (rn, same);
1085
1086 if (same)
1087 {
1088 newrib_free (same);
1089 route_unlock_node (rn);
1090 }
1091
1092 route_unlock_node (rn);
1093
1094 return 0;
1095}
1096
1097/* Delete all added route and close rib. */
1098void
1099rib_close_ipv4 ()
1100{
1101 struct route_node *rn;
1102 struct rib *rib;
1103
1104 for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
1105 for (rib = rn->info; rib; rib = rib->next)
1106 if (! RIB_SYSTEM_ROUTE (rib)
1107 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1108 rib_uninstall_kernel (rn, rib);
1109}
1110
1111/* Install static route into rib. */
1112void
1113static_ipv4_install (struct prefix_ipv4 *p, struct static_ipv4 *si)
1114{
1115 struct rib *rib;
1116 struct route_node *rn;
1117
1118 /* Lookup existing route */
1119 rn = route_node_get (rib_table_ipv4, (struct prefix *) p);
1120 for (rib = rn->info; rib; rib = rib->next)
1121 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1122 break;
1123
1124 if (rib)
1125 {
1126 /* Same distance static route is there. Update it with new
1127 nexthop. */
1128 rib_uninstall (rn, rib);
1129 route_unlock_node (rn);
1130
1131 switch (si->type)
1132 {
1133 case STATIC_IPV4_GATEWAY:
1134 nexthop_ipv4_add (rib, &si->gate.ipv4);
1135 break;
1136 case STATIC_IPV4_IFNAME:
1137 nexthop_ifname_add (rib, si->gate.ifname);
1138 break;
1139 }
1140 rib_process (rn, NULL);
1141 }
1142 else
1143 {
1144 /* This is new static route. */
1145 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1146 memset (rib, 0, sizeof (struct rib));
1147
1148 rib->type = ZEBRA_ROUTE_STATIC;
1149 rib->distance = si->distance;
1150 rib->metric = 0;
1151 rib->nexthop_num = 0;
1152
1153 switch (si->type)
1154 {
1155 case STATIC_IPV4_GATEWAY:
1156 nexthop_ipv4_add (rib, &si->gate.ipv4);
1157 break;
1158 case STATIC_IPV4_IFNAME:
1159 nexthop_ifname_add (rib, si->gate.ifname);
1160 break;
1161 }
1162
1163 /* Link this rib to the tree. */
1164 rib_addnode (rn, rib);
1165
1166 /* Process this prefix. */
1167 rib_process (rn, NULL);
1168 }
1169}
1170
1171int
1172static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1173{
1174 if (nexthop->type == NEXTHOP_TYPE_IPV4
1175 && si->type == STATIC_IPV4_GATEWAY
1176 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1177 return 1;
1178 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1179 && si->type == STATIC_IPV4_IFNAME
1180 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1181 return 1;
1182 return 0;;
1183}
1184
1185/* Uninstall static route from RIB. */
1186void
1187static_ipv4_uninstall (struct prefix_ipv4 *p, struct static_ipv4 *si)
1188{
1189 struct route_node *rn;
1190 struct rib *rib;
1191 struct nexthop *nexthop;
1192
1193 /* Lookup existing route with type and distance. */
1194 rn = route_node_lookup (rib_table_ipv4, (struct prefix *) p);
1195 if (! rn)
1196 return;
1197
1198 for (rib = rn->info; rib; rib = rib->next)
1199 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1200 break;
1201 if (! rib)
1202 {
1203 route_unlock_node (rn);
1204 return;
1205 }
1206
1207 /* Lookup nexthop. */
1208 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1209 if (static_ipv4_nexthop_same (nexthop, si))
1210 break;
1211
1212 /* Can't find nexthop. */
1213 if (! nexthop)
1214 {
1215 route_unlock_node (rn);
1216 return;
1217 }
1218
1219 /* Check nexthop. */
1220 if (rib->nexthop_num == 1)
1221 {
1222 rib_delnode (rn, rib);
1223 rib_process (rn, rib);
1224 newrib_free (rib);
1225 route_unlock_node (rn);
1226 }
1227 else
1228 {
1229 rib_uninstall (rn, rib);
1230 nexthop_delete (rib, nexthop);
1231 nexthop_free (nexthop);
1232 rib_process (rn, rib);
1233 }
1234
1235 /* Unlock node. */
1236 route_unlock_node (rn);
1237}
1238
1239/* Add static route into static route configuration. */
1240int
1241static_ipv4_add (struct prefix_ipv4 *p, struct in_addr *gate, char *ifname,
1242 u_char distance, int table)
1243{
1244 u_char type = 0;
1245 struct route_node *rn;
1246 struct static_ipv4 *si;
1247 struct static_ipv4 *pp;
1248 struct static_ipv4 *cp;
1249
1250 /* Lookup static route prefix. */
1251 rn = route_node_get (static_table_ipv4, (struct prefix *) p);
1252
1253 /* Make flags. */
1254 if (gate)
1255 type = STATIC_IPV4_GATEWAY;
1256 if (ifname)
1257 type = STATIC_IPV4_IFNAME;
1258
1259 /* Do nothing if there is a same static route. */
1260 for (si = rn->info; si; si = si->next)
1261 {
1262 if (distance == si->distance
1263 && type == si->type
1264 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1265 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1266 {
1267 route_unlock_node (rn);
1268 return 0;
1269 }
1270 }
1271
1272 /* Make new static route structure. */
1273 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
1274 memset (si, 0, sizeof (struct static_ipv4));
1275
1276 si->type = type;
1277 si->distance = distance;
1278
1279 if (gate)
1280 si->gate.ipv4 = *gate;
1281 if (ifname)
1282 si->gate.ifname = XSTRDUP (0, ifname);
1283
1284 /* Add new static route information to the tree with sort by
1285 distance value and gateway address. */
1286 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
1287 {
1288 if (si->distance < cp->distance)
1289 break;
1290 if (si->distance > cp->distance)
1291 continue;
1292 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
1293 {
1294 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
1295 break;
1296 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
1297 continue;
1298 }
1299 }
1300
1301 /* Make linked list. */
1302 if (pp)
1303 pp->next = si;
1304 else
1305 rn->info = si;
1306 if (cp)
1307 cp->prev = si;
1308 si->prev = pp;
1309 si->next = cp;
1310
1311 /* Install into rib. */
1312 static_ipv4_install (p, si);
1313
1314 return 1;
1315}
1316
1317/* Delete static route from static route configuration. */
1318int
1319static_ipv4_delete (struct prefix_ipv4 *p, struct in_addr *gate, char *ifname,
1320 u_char distance, int table)
1321{
1322 u_char type = 0;
1323 struct route_node *rn;
1324 struct static_ipv4 *si;
1325
1326 /* Lookup static route prefix. */
1327 rn = route_node_lookup (static_table_ipv4, (struct prefix *) p);
1328 if (! rn)
1329 return 0;
1330
1331 /* Make flags. */
1332 if (gate)
1333 type = STATIC_IPV4_GATEWAY;
1334 if (ifname)
1335 type = STATIC_IPV4_IFNAME;
1336
1337 /* Find same static route is the tree */
1338 for (si = rn->info; si; si = si->next)
1339 if (distance == si->distance
1340 && type == si->type
1341 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1342 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1343 break;
1344
1345 /* Can't find static route. */
1346 if (! si)
1347 {
1348 route_unlock_node (rn);
1349 return 0;
1350 }
1351
1352 /* Install into rib. */
1353 static_ipv4_uninstall (p, si);
1354
1355 /* Unlink static route from linked list. */
1356 if (si->prev)
1357 si->prev->next = si->next;
1358 else
1359 rn->info = si->next;
1360 if (si->next)
1361 si->next->prev = si->prev;
1362
1363 /* Free static route configuration. */
1364 XFREE (MTYPE_STATIC_IPV4, si);
1365
1366 return 1;
1367}
1368
1369/* Write IPv4 static route configuration. */
1370int
1371static_ipv4_write (struct vty *vty)
1372{
1373 struct route_node *rn;
1374 struct static_ipv4 *si;
1375 int write;
1376
1377 write = 0;
1378
1379 for (rn = route_top (static_table_ipv4); rn; rn = route_next (rn))
1380 for (si = rn->info; si; si = si->next)
1381 {
1382 vty_out (vty, "ip route %s/%d", inet_ntoa (rn->p.u.prefix4),
1383 rn->p.prefixlen);
1384
1385 switch (si->type)
1386 {
1387 case STATIC_IPV4_GATEWAY:
1388 vty_out (vty, " %s", inet_ntoa (si->gate.ipv4));
1389 break;
1390 case STATIC_IPV4_IFNAME:
1391 vty_out (vty, " %s", si->gate.ifname);
1392 break;
1393 }
1394
1395 if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
1396 vty_out (vty, " %d", si->distance);
1397 vty_out (vty, "%s", VTY_NEWLINE);
1398
1399 write = 1;
1400 }
1401 return write;
1402}
1403
1404/* General fucntion for static route. */
1405int
1406static_ipv4_func (struct vty *vty, int add_cmd,
1407 char *dest_str, char *mask_str, char *gate_str,
1408 char *distance_str)
1409{
1410 int ret;
1411 u_char distance;
1412 struct prefix_ipv4 p;
1413 struct in_addr gate;
1414 struct in_addr mask;
1415 char *ifname;
1416 int table = rtm_table_default;
1417
1418 ret = str2prefix_ipv4 (dest_str, &p);
1419 if (ret <= 0)
1420 {
1421 vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
1422 return CMD_WARNING;
1423 }
1424
1425 /* Cisco like mask notation. */
1426 if (mask_str)
1427 {
1428 ret = inet_aton (mask_str, &mask);
1429 if (ret == 0)
1430 {
1431 vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
1432 return CMD_WARNING;
1433 }
1434 p.prefixlen = ip_masklen (mask);
1435 }
1436
1437 /* Apply mask for given prefix. */
1438 apply_mask_ipv4 (&p);
1439
1440 /* Administrative distance. */
1441 if (distance_str)
1442 distance = atoi (distance_str);
1443 else
1444 distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
1445
1446 /* When gateway is A.B.C.D format, gate is treated as nexthop
1447 address other case gate is treated as interface name. */
1448 ret = inet_aton (gate_str, &gate);
1449 if (ret)
1450 ifname = NULL;
1451 else
1452 ifname = gate_str;
1453
1454 if (add_cmd)
1455 static_ipv4_add (&p, ifname ? NULL : &gate, ifname, distance, table);
1456 else
1457 static_ipv4_delete (&p, ifname ? NULL : &gate, ifname, distance, table);
1458
1459 return CMD_SUCCESS;
1460}
1461
1462/* Static route configuration. */
1463DEFUN (ip_route,
1464 ip_route_cmd,
1465 "ip route A.B.C.D/M (A.B.C.D|INTERFACE)",
1466 IP_STR
1467 "Establish static routes\n"
1468 "IP destination prefix (e.g. 10.0.0.0/8)\n"
1469 "IP gateway address\n"
1470 "IP gateway interface name\n")
1471{
1472 return static_ipv4_func (vty, 1, argv[0], NULL, argv[1], NULL);
1473}
1474
1475DEFUN (ip_route_mask,
1476 ip_route_mask_cmd,
1477 "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE)",
1478 IP_STR
1479 "Establish static routes\n"
1480 "IP destination prefix\n"
1481 "IP destination prefix mask\n"
1482 "IP gateway address\n"
1483 "IP gateway interface name\n")
1484{
1485 return static_ipv4_func (vty, 1, argv[0], argv[1], argv[2], NULL);
1486}
1487
1488DEFUN (ip_route_pref,
1489 ip_route_pref_cmd,
1490 "ip route A.B.C.D/M (A.B.C.D|INTERFACE) <1-255>",
1491 IP_STR
1492 "Establish static routes\n"
1493 "IP destination prefix (e.g. 10.0.0.0/8)\n"
1494 "IP gateway address\n"
1495 "IP gateway interface name\n"
1496 "Distance value for this route\n")
1497{
1498 return static_ipv4_func (vty, 1, argv[0], NULL, argv[1], argv[2]);
1499}
1500
1501DEFUN (ip_route_mask_pref,
1502 ip_route_mask_pref_cmd,
1503 "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) <1-255>",
1504 IP_STR
1505 "Establish static routes\n"
1506 "IP destination prefix\n"
1507 "IP destination prefix mask\n"
1508 "IP gateway address\n"
1509 "IP gateway interface name\n"
1510 "Distance value for this route\n")
1511{
1512 return static_ipv4_func (vty, 1, argv[0], argv[1], argv[2], argv[3]);
1513}
1514
1515DEFUN (no_ip_route,
1516 no_ip_route_cmd,
1517 "no ip route A.B.C.D/M (A.B.C.D|INTERFACE)",
1518 NO_STR
1519 IP_STR
1520 "Establish static routes\n"
1521 "IP destination prefix (e.g. 10.0.0.0/8)\n"
1522 "IP gateway address\n"
1523 "IP gateway interface name\n")
1524{
1525 return static_ipv4_func (vty, 0, argv[0], NULL, argv[1], NULL);
1526}
1527
1528DEFUN (no_ip_route_mask,
1529 no_ip_route_mask_cmd,
1530 "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE)",
1531 NO_STR
1532 IP_STR
1533 "Establish static routes\n"
1534 "IP destination prefix\n"
1535 "IP destination prefix mask\n"
1536 "IP gateway address\n"
1537 "IP gateway interface name\n")
1538{
1539 return static_ipv4_func (vty, 0, argv[0], argv[1], argv[2], NULL);
1540}
1541
1542DEFUN (no_ip_route_pref,
1543 no_ip_route_pref_cmd,
1544 "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) <1-255>",
1545 NO_STR
1546 IP_STR
1547 "Establish static routes\n"
1548 "IP destination prefix (e.g. 10.0.0.0/8)\n"
1549 "IP gateway address\n"
1550 "IP gateway interface name\n"
1551 "Distance value for this route\n")
1552{
1553 return static_ipv4_func (vty, 0, argv[0], NULL, argv[1], argv[2]);
1554}
1555
1556DEFUN (no_ip_route_mask_pref,
1557 no_ip_route_mask_pref_cmd,
1558 "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) <1-255>",
1559 NO_STR
1560 IP_STR
1561 "Establish static routes\n"
1562 "IP destination prefix\n"
1563 "IP destination prefix mask\n"
1564 "IP gateway address\n"
1565 "IP gateway interface name\n"
1566 "Distance value for this route\n")
1567{
1568 return static_ipv4_func (vty, 0, argv[0], argv[1], argv[2], argv[3]);
1569}
1570
1571/* New RIB. Detailed information for IPv4 route. */
1572void
1573vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
1574{
1575 struct rib *rib;
1576 struct nexthop *nexthop;
1577
1578 for (rib = rn->info; rib; rib = rib->next)
1579 {
1580 vty_out (vty, "Routing entry for %s/%d%s",
1581 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
1582 VTY_NEWLINE);
1583 vty_out (vty, " Known via \"%s\"", route_info[rib->type].str);
1584 vty_out (vty, ", distance %d, metric %d", rib->distance, rib->metric);
1585 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1586 vty_out (vty, ", best");
1587 if (rib->refcnt)
1588 vty_out (vty, ", refcnt %ld", rib->refcnt);
1589 vty_out (vty, "%s", VTY_NEWLINE);
1590
1591#define ONE_DAY_SECOND 60*60*24
1592#define ONE_WEEK_SECOND 60*60*24*7
1593 if (rib->type == ZEBRA_ROUTE_RIP
1594 || rib->type == ZEBRA_ROUTE_OSPF
1595 || rib->type == ZEBRA_ROUTE_ISIS
1596 || rib->type == ZEBRA_ROUTE_BGP)
1597 {
1598 time_t uptime;
1599 struct tm *tm;
1600
1601 uptime = time (NULL);
1602 uptime -= rib->uptime;
1603 tm = gmtime (&uptime);
1604
1605 vty_out (vty, " Last update ");
1606
1607 if (uptime < ONE_DAY_SECOND)
1608 vty_out (vty, "%02d:%02d:%02d",
1609 tm->tm_hour, tm->tm_min, tm->tm_sec);
1610 else if (uptime < ONE_WEEK_SECOND)
1611 vty_out (vty, "%dd%02dh%02dm",
1612 tm->tm_yday, tm->tm_hour, tm->tm_min);
1613 else
1614 vty_out (vty, "%02dw%dd%02dh",
1615 tm->tm_yday/7,
1616 tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
1617 vty_out (vty, " ago%s", VTY_NEWLINE);
1618 }
1619
1620 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1621 {
1622 vty_out (vty, " %c",
1623 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
1624
1625 switch (nexthop->type)
1626 {
1627 case NEXTHOP_TYPE_IPV4:
1628 case NEXTHOP_TYPE_IPV4_IFINDEX:
1629 vty_out (vty, " %s", inet_ntoa (nexthop->gate.ipv4));
1630 if (nexthop->ifindex)
1631 vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex));
1632 break;
1633 case NEXTHOP_TYPE_IFINDEX:
1634 vty_out (vty, " directly connected, %s",
1635 ifindex2ifname (nexthop->ifindex));
1636 break;
1637 case NEXTHOP_TYPE_IFNAME:
1638 vty_out (vty, " directly connected, %s",
1639 nexthop->ifname);
1640 break;
1641 default:
1642 break;
1643 }
1644 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1645 vty_out (vty, " inactive");
1646
1647 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1648 {
1649 vty_out (vty, " (recursive");
1650
1651 switch (nexthop->rtype)
1652 {
1653 case NEXTHOP_TYPE_IPV4:
1654 case NEXTHOP_TYPE_IPV4_IFINDEX:
1655 vty_out (vty, " via %s)", inet_ntoa (nexthop->rgate.ipv4));
1656 break;
1657 case NEXTHOP_TYPE_IFINDEX:
1658 case NEXTHOP_TYPE_IFNAME:
1659 vty_out (vty, " is directly connected, %s)",
1660 ifindex2ifname (nexthop->rifindex));
1661 break;
1662 default:
1663 break;
1664 }
1665 }
1666 vty_out (vty, "%s", VTY_NEWLINE);
1667 }
1668 vty_out (vty, "%s", VTY_NEWLINE);
1669 }
1670}
1671
1672void
1673vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
1674{
1675 struct nexthop *nexthop;
1676 int len = 0;
1677 char buf[BUFSIZ];
1678
1679 /* Nexthop information. */
1680 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1681 {
1682 if (nexthop == rib->nexthop)
1683 {
1684 /* Prefix information. */
1685 len = vty_out (vty, "%c%c%c %s/%d",
1686 route_info[rib->type].c,
1687 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)
1688 ? '>' : ' ',
1689 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
1690 ? '*' : ' ',
1691 inet_ntop (AF_INET, &rn->p.u.prefix, buf, BUFSIZ),
1692 rn->p.prefixlen);
1693
1694 /* Distance and metric display. */
1695 if (rib->type != ZEBRA_ROUTE_CONNECT
1696 && rib->type != ZEBRA_ROUTE_KERNEL)
1697 len += vty_out (vty, " [%d/%d]", rib->distance,
1698 rib->metric);
1699 }
1700 else
1701 vty_out (vty, " %c%*c",
1702 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
1703 ? '*' : ' ',
1704 len - 3, ' ');
1705
1706 switch (nexthop->type)
1707 {
1708 case NEXTHOP_TYPE_IPV4:
1709 case NEXTHOP_TYPE_IPV4_IFINDEX:
1710 vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4));
1711 if (nexthop->ifindex)
1712 vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex));
1713 break;
1714 case NEXTHOP_TYPE_IFINDEX:
1715 vty_out (vty, " is directly connected, %s",
1716 ifindex2ifname (nexthop->ifindex));
1717 break;
1718 case NEXTHOP_TYPE_IFNAME:
1719 vty_out (vty, " is directly connected, %s",
1720 nexthop->ifname);
1721 break;
1722 default:
1723 break;
1724 }
1725 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1726 vty_out (vty, " inactive");
1727
1728 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1729 {
1730 vty_out (vty, " (recursive");
1731
1732 switch (nexthop->rtype)
1733 {
1734 case NEXTHOP_TYPE_IPV4:
1735 case NEXTHOP_TYPE_IPV4_IFINDEX:
1736 vty_out (vty, " via %s)", inet_ntoa (nexthop->rgate.ipv4));
1737 break;
1738 case NEXTHOP_TYPE_IFINDEX:
1739 case NEXTHOP_TYPE_IFNAME:
1740 vty_out (vty, " is directly connected, %s)",
1741 ifindex2ifname (nexthop->rifindex));
1742 break;
1743 default:
1744 break;
1745 }
1746 }
1747
1748 if (rib->type == ZEBRA_ROUTE_RIP
1749 || rib->type == ZEBRA_ROUTE_OSPF
1750 || rib->type == ZEBRA_ROUTE_ISIS
1751 || rib->type == ZEBRA_ROUTE_BGP)
1752 {
1753 time_t uptime;
1754 struct tm *tm;
1755
1756 uptime = time (NULL);
1757 uptime -= rib->uptime;
1758 tm = gmtime (&uptime);
1759
1760#define ONE_DAY_SECOND 60*60*24
1761#define ONE_WEEK_SECOND 60*60*24*7
1762
1763 if (uptime < ONE_DAY_SECOND)
1764 vty_out (vty, ", %02d:%02d:%02d",
1765 tm->tm_hour, tm->tm_min, tm->tm_sec);
1766 else if (uptime < ONE_WEEK_SECOND)
1767 vty_out (vty, ", %dd%02dh%02dm",
1768 tm->tm_yday, tm->tm_hour, tm->tm_min);
1769 else
1770 vty_out (vty, ", %02dw%dd%02dh",
1771 tm->tm_yday/7,
1772 tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
1773 }
1774 vty_out (vty, "%s", VTY_NEWLINE);
1775 }
1776}
1777
1778#define SHOW_ROUTE_V4_HEADER "Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,%s I - IS-IS, %s B - BGP, > - selected route, * - FIB route%s%s"
1779
1780DEFUN (show_ip_route,
1781 show_ip_route_cmd,
1782 "show ip route",
1783 SHOW_STR
1784 IP_STR
1785 "IP routing table\n")
1786{
1787 struct route_node *rn;
1788 struct rib *rib;
1789 int first = 1;
1790
1791 /* Show all IPv4 routes. */
1792 for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
1793 for (rib = rn->info; rib; rib = rib->next)
1794 {
1795 if (first)
1796 {
1797 vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
1798 first = 0;
1799 }
1800 vty_show_ip_route (vty, rn, rib);
1801 }
1802 return CMD_SUCCESS;
1803}
1804
1805DEFUN (show_ip_route_prefix_longer,
1806 show_ip_route_prefix_longer_cmd,
1807 "show ip route A.B.C.D/M longer-prefixes",
1808 SHOW_STR
1809 IP_STR
1810 "IP routing table\n"
1811 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1812 "Show route matching the specified Network/Mask pair only\n")
1813{
1814 struct route_node *rn;
1815 struct rib *rib;
1816 struct prefix p;
1817 int ret;
1818 int first = 1;
1819
1820 ret = str2prefix (argv[0], &p);
1821 if (! ret)
1822 {
1823 vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
1824 return CMD_WARNING;
1825 }
1826
1827 /* Show matched type IPv4 routes. */
1828 for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
1829 for (rib = rn->info; rib; rib = rib->next)
1830 if (prefix_match (&p, &rn->p))
1831 {
1832 if (first)
1833 {
1834 vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
1835 first = 0;
1836 }
1837 vty_show_ip_route (vty, rn, rib);
1838 }
1839 return CMD_SUCCESS;
1840}
1841
1842DEFUN (show_ip_route_supernets,
1843 show_ip_route_supernets_cmd,
1844 "show ip route supernets-only",
1845 SHOW_STR
1846 IP_STR
1847 "IP routing table\n"
1848 "Show supernet entries only\n")
1849{
1850 struct route_node *rn;
1851 struct rib *rib;
1852 u_int32_t addr;
1853 int first = 1;
1854
1855
1856 /* Show matched type IPv4 routes. */
1857 for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
1858 for (rib = rn->info; rib; rib = rib->next)
1859 {
1860 addr = ntohl (rn->p.u.prefix4.s_addr);
1861
1862 if ((IN_CLASSC (addr) && rn->p.prefixlen < 24)
1863 || (IN_CLASSB (addr) && rn->p.prefixlen < 16)
1864 || (IN_CLASSA (addr) && rn->p.prefixlen < 8))
1865 {
1866 if (first)
1867 {
1868 vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE,
1869 VTY_NEWLINE, VTY_NEWLINE);
1870 first = 0;
1871 }
1872 vty_show_ip_route (vty, rn, rib);
1873 }
1874 }
1875 return CMD_SUCCESS;
1876}
1877
1878
1879DEFUN (show_ip_route_protocol,
1880 show_ip_route_protocol_cmd,
1881 "show ip route (bgp|connected|kernel|ospf|isis|rip|static)",
1882 SHOW_STR
1883 IP_STR
1884 "IP routing table\n"
1885 "Border Gateway Protocol (BGP)\n"
1886 "Connected\n"
1887 "Kernel\n"
1888 "Open Shortest Path First (OSPF)\n"
1889 "ISO IS-IS (ISIS)\n"
1890 "Routing Information Protocol (RIP)\n"
1891 "Static routes\n")
1892{
1893 int type;
1894 struct route_node *rn;
1895 struct rib *rib;
1896 int first = 1;
1897
1898 if (strncmp (argv[0], "b", 1) == 0)
1899 type = ZEBRA_ROUTE_BGP;
1900 else if (strncmp (argv[0], "c", 1) == 0)
1901 type = ZEBRA_ROUTE_CONNECT;
1902 else if (strncmp (argv[0], "k", 1) ==0)
1903 type = ZEBRA_ROUTE_KERNEL;
1904 else if (strncmp (argv[0], "o", 1) == 0)
1905 type = ZEBRA_ROUTE_OSPF;
1906 else if (strncmp (argv[0], "i", 1) == 0)
1907 type = ZEBRA_ROUTE_ISIS;
1908 else if (strncmp (argv[0], "r", 1) == 0)
1909 type = ZEBRA_ROUTE_RIP;
1910 else if (strncmp (argv[0], "s", 1) == 0)
1911 type = ZEBRA_ROUTE_STATIC;
1912 else
1913 {
1914 vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
1915 return CMD_WARNING;
1916 }
1917
1918 /* Show matched type IPv4 routes. */
1919 for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
1920 for (rib = rn->info; rib; rib = rib->next)
1921 if (rib->type == type)
1922 {
1923 if (first)
1924 {
1925 vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE,
1926 VTY_NEWLINE, VTY_NEWLINE);
1927 first = 0;
1928 }
1929 vty_show_ip_route (vty, rn, rib);
1930 }
1931 return CMD_SUCCESS;
1932}
1933
1934DEFUN (show_ip_route_addr,
1935 show_ip_route_addr_cmd,
1936 "show ip route A.B.C.D",
1937 SHOW_STR
1938 IP_STR
1939 "IP routing table\n"
1940 "Network in the IP routing table to display\n")
1941{
1942 int ret;
1943 struct prefix_ipv4 p;
1944 struct route_node *rn;
1945
1946 ret = str2prefix_ipv4 (argv[0], &p);
1947 if (ret <= 0)
1948 {
1949 vty_out (vty, "Malformed IPv4 address%s", VTY_NEWLINE);
1950 return CMD_WARNING;
1951 }
1952
1953 rn = route_node_match (rib_table_ipv4, (struct prefix *) &p);
1954 if (! rn)
1955 {
1956 vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
1957 return CMD_WARNING;
1958 }
1959
1960 vty_show_ip_route_detail (vty, rn);
1961
1962 route_unlock_node (rn);
1963
1964 return CMD_SUCCESS;
1965}
1966
1967DEFUN (show_ip_route_prefix,
1968 show_ip_route_prefix_cmd,
1969 "show ip route A.B.C.D/M",
1970 SHOW_STR
1971 IP_STR
1972 "IP routing table\n"
1973 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
1974{
1975 int ret;
1976 struct prefix_ipv4 p;
1977 struct route_node *rn;
1978
1979 ret = str2prefix_ipv4 (argv[0], &p);
1980 if (ret <= 0)
1981 {
1982 vty_out (vty, "Malformed IPv4 address%s", VTY_NEWLINE);
1983 return CMD_WARNING;
1984 }
1985
1986 rn = route_node_match (rib_table_ipv4, (struct prefix *) &p);
1987 if (! rn || rn->p.prefixlen != p.prefixlen)
1988 {
1989 vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
1990 return CMD_WARNING;
1991 }
1992
1993 vty_show_ip_route_detail (vty, rn);
1994
1995 route_unlock_node (rn);
1996
1997 return CMD_SUCCESS;
1998}
1999
2000#ifdef HAVE_IPV6
2001int
2002rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
2003 struct in6_addr *gate, unsigned int ifindex, int table)
2004{
2005 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix))
2006 return 1;
2007 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
2008 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
2009 {
2010 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
2011 return 1;
2012 }
2013 return 0;
2014}
2015
2016int
2017rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
2018 struct in6_addr *gate, unsigned int ifindex, int table)
2019{
2020 struct rib *rib;
2021 struct rib *same = NULL;
2022 struct route_node *rn;
2023 struct nexthop *nexthop;
2024
2025 int distance;
2026 u_int32_t metric = 0;
2027
2028 /* Make sure mask is applied. */
2029 apply_mask_ipv6 (p);
2030
2031 /* Set default distance by route type. */
2032 distance = route_info[type].distance;
2033
2034 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2035 distance = 200;
2036
2037 /* Make new rib. */
2038 if (!table)
2039 table = RT_TABLE_MAIN;
2040
2041 /* Filter bogus route. */
2042 if (rib_bogus_ipv6 (type, p, gate, ifindex, table))
2043 return 0;
2044
2045 /* Lookup route node.*/
2046 rn = route_node_get (rib_table_ipv6, (struct prefix *) p);
2047
2048 /* If same type of route are installed, treat it as a implicit
2049 withdraw. */
2050 for (rib = rn->info; rib; rib = rib->next)
2051 {
2052 if (rib->type == ZEBRA_ROUTE_CONNECT)
2053 {
2054 nexthop = rib->nexthop;
2055
2056 if (rib->type == type
2057 && (! table || rib->table == table)
2058 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
2059 && nexthop->ifindex == ifindex)
2060 {
2061 rib->refcnt++;
2062 return 0;
2063 }
2064 }
2065 else if (rib->type == type
2066 && (! table || (rib->table == table)))
2067 {
2068 same = rib;
2069 rib_delnode (rn, same);
2070 route_unlock_node (rn);
2071 break;
2072 }
2073 }
2074
2075 /* Allocate new rib structure. */
2076 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
2077 memset (rib, 0, sizeof (struct rib));
2078 rib->type = type;
2079 rib->distance = distance;
2080 rib->flags = flags;
2081 rib->metric = metric;
2082 rib->table = table;
2083 rib->nexthop_num = 0;
2084 rib->uptime = time (NULL);
2085
2086 /* Nexthop settings. */
2087 if (gate)
2088 {
2089 if (ifindex)
2090 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2091 else
2092 nexthop_ipv6_add (rib, gate);
2093 }
2094 else
2095 nexthop_ifindex_add (rib, ifindex);
2096
2097 /* If this route is kernel route, set FIB flag to the route. */
2098 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2099 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2100 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2101
2102 /* Link new rib to node.*/
2103 rib_addnode (rn, rib);
2104
2105 /* Process this route node. */
2106 rib_process (rn, same);
2107
2108 /* Free implicit route.*/
2109 if (same)
2110 newrib_free (same);
2111
2112 return 0;
2113}
2114
2115int
2116rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
2117 struct in6_addr *gate, unsigned int ifindex, int table)
2118{
2119 struct route_node *rn;
2120 struct rib *rib;
2121 struct rib *fib = NULL;
2122 struct rib *same = NULL;
2123 struct nexthop *nexthop;
2124 char buf1[BUFSIZ];
2125 char buf2[BUFSIZ];
2126
2127 /* Apply mask. */
2128 apply_mask_ipv6 (p);
2129
2130 /* Lookup route node. */
2131 rn = route_node_lookup (rib_table_ipv6, (struct prefix *) p);
2132 if (! rn)
2133 {
2134 if (IS_ZEBRA_DEBUG_KERNEL)
2135 {
2136 if (gate)
2137 zlog_info ("route %s/%d via %s ifindex %d doesn't exist in rib",
2138 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2139 p->prefixlen,
2140 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2141 ifindex);
2142 else
2143 zlog_info ("route %s/%d ifindex %d doesn't exist in rib",
2144 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2145 p->prefixlen,
2146 ifindex);
2147 }
2148 return ZEBRA_ERR_RTNOEXIST;
2149 }
2150
2151 /* Lookup same type route. */
2152 for (rib = rn->info; rib; rib = rib->next)
2153 {
2154 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2155 fib = rib;
2156
2157 if (rib->type == ZEBRA_ROUTE_CONNECT)
2158 {
2159 nexthop = rib->nexthop;
2160
2161 if (rib->type == type
2162 && (! table || rib->table == table)
2163 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
2164 && nexthop->ifindex == ifindex)
2165 {
2166 if (rib->refcnt)
2167 {
2168 rib->refcnt--;
2169 route_unlock_node (rn);
2170 route_unlock_node (rn);
2171 return 0;
2172 }
2173 same = rib;
2174 break;
2175 }
2176 }
2177 else
2178 {
2179 if (rib->type == type
2180 && (! table || rib->table == table))
2181 {
2182 same = rib;
2183 break;
2184 }
2185 }
2186 }
2187
2188 /* If same type of route can't be found and this message is from
2189 kernel. */
2190 if (! same)
2191 {
2192 if (fib && type == ZEBRA_ROUTE_KERNEL)
2193 {
2194 /* Unset flags. */
2195 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2196 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2197
2198 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2199 }
2200 else
2201 {
2202 if (IS_ZEBRA_DEBUG_KERNEL)
2203 {
2204 if (gate)
2205 zlog_info ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
2206 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2207 p->prefixlen,
2208 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2209 ifindex,
2210 type);
2211 else
2212 zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib",
2213 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2214 p->prefixlen,
2215 ifindex,
2216 type);
2217 }
2218 route_unlock_node (rn);
2219 return ZEBRA_ERR_RTNOEXIST;
2220 }
2221 }
2222
2223 if (same)
2224 rib_delnode (rn, same);
2225
2226 /* Process changes. */
2227 rib_process (rn, same);
2228
2229 if (same)
2230 {
2231 newrib_free (same);
2232 route_unlock_node (rn);
2233 }
2234
2235 route_unlock_node (rn);
2236
2237 return 0;
2238}
2239
2240/* Delete non system routes. */
2241void
2242rib_close_ipv6 ()
2243{
2244 struct route_node *rn;
2245 struct rib *rib;
2246
2247 for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
2248 for (rib = rn->info; rib; rib = rib->next)
2249 if (! RIB_SYSTEM_ROUTE (rib)
2250 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2251 rib_uninstall_kernel (rn, rib);
2252}
2253
2254/* Install static route into rib. */
2255void
2256static_ipv6_install (struct prefix_ipv6 *p, struct static_ipv6 *si)
2257{
2258 struct rib *rib;
2259 struct route_node *rn;
2260
2261 /* Lookup existing route */
2262 rn = route_node_get (rib_table_ipv6, (struct prefix *) p);
2263 for (rib = rn->info; rib; rib = rib->next)
2264 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2265 break;
2266
2267 if (rib)
2268 {
2269 /* Same distance static route is there. Update it with new
2270 nexthop. */
2271 rib_uninstall (rn, rib);
2272 route_unlock_node (rn);
2273
2274 switch (si->type)
2275 {
2276 case STATIC_IPV6_GATEWAY:
2277 nexthop_ipv6_add (rib, &si->ipv6);
2278 break;
2279 case STATIC_IPV6_IFNAME:
2280 nexthop_ifname_add (rib, si->ifname);
2281 break;
2282 case STATIC_IPV6_GATEWAY_IFNAME:
2283 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2284 break;
2285 }
2286 rib_process (rn, NULL);
2287 }
2288 else
2289 {
2290 /* This is new static route. */
2291 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
2292 memset (rib, 0, sizeof (struct rib));
2293
2294 rib->type = ZEBRA_ROUTE_STATIC;
2295 rib->distance = si->distance;
2296 rib->metric = 0;
2297 rib->nexthop_num = 0;
2298
2299 switch (si->type)
2300 {
2301 case STATIC_IPV6_GATEWAY:
2302 nexthop_ipv6_add (rib, &si->ipv6);
2303 break;
2304 case STATIC_IPV6_IFNAME:
2305 nexthop_ifname_add (rib, si->ifname);
2306 break;
2307 case STATIC_IPV6_GATEWAY_IFNAME:
2308 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2309 break;
2310 }
2311
2312 /* Link this rib to the tree. */
2313 rib_addnode (rn, rib);
2314
2315 /* Process this prefix. */
2316 rib_process (rn, NULL);
2317 }
2318}
2319
2320int
2321static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2322{
2323 if (nexthop->type == NEXTHOP_TYPE_IPV6
2324 && si->type == STATIC_IPV6_GATEWAY
2325 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2326 return 1;
2327 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2328 && si->type == STATIC_IPV6_IFNAME
2329 && strcmp (nexthop->ifname, si->ifname) == 0)
2330 return 1;
2331 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2332 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2333 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2334 && strcmp (nexthop->ifname, si->ifname) == 0)
2335 return 1;
2336 return 0;;
2337}
2338
2339void
2340static_ipv6_uninstall (struct prefix_ipv6 *p, struct static_ipv6 *si)
2341{
2342 struct route_node *rn;
2343 struct rib *rib;
2344 struct nexthop *nexthop;
2345
2346 /* Lookup existing route with type and distance. */
2347 rn = route_node_lookup (rib_table_ipv6, (struct prefix *) p);
2348 if (! rn)
2349 return;
2350
2351 for (rib = rn->info; rib; rib = rib->next)
2352 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2353 break;
2354 if (! rib)
2355 {
2356 route_unlock_node (rn);
2357 return;
2358 }
2359
2360 /* Lookup nexthop. */
2361 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2362 if (static_ipv6_nexthop_same (nexthop, si))
2363 break;
2364
2365 /* Can't find nexthop. */
2366 if (! nexthop)
2367 {
2368 route_unlock_node (rn);
2369 return;
2370 }
2371
2372 /* Check nexthop. */
2373 if (rib->nexthop_num == 1)
2374 {
2375 rib_delnode (rn, rib);
2376 rib_process (rn, rib);
2377 newrib_free (rib);
2378 route_unlock_node (rn);
2379 }
2380 else
2381 {
2382 rib_uninstall (rn, rib);
2383 nexthop_delete (rib, nexthop);
2384 nexthop_free (nexthop);
2385 rib_process (rn, rib);
2386 }
2387
2388 /* Unlock node. */
2389 route_unlock_node (rn);
2390}
2391
2392/* Add static route into static route configuration. */
2393int
2394static_ipv6_add (struct prefix_ipv6 *p, u_char type, struct in6_addr *gate,
2395 char *ifname, u_char distance, int table)
2396{
2397 struct route_node *rn;
2398 struct static_ipv6 *si;
2399 struct static_ipv6 *pp;
2400 struct static_ipv6 *cp;
2401
2402 /* Lookup static route prefix. */
2403 rn = route_node_get (static_table_ipv6, (struct prefix *) p);
2404
2405 /* Do nothing if there is a same static route. */
2406 for (si = rn->info; si; si = si->next)
2407 {
2408 if (distance == si->distance
2409 && type == si->type
2410 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2411 && (! ifname || strcmp (ifname, si->ifname) == 0))
2412 {
2413 route_unlock_node (rn);
2414 return 0;
2415 }
2416 }
2417
2418 /* Make new static route structure. */
2419 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2420 memset (si, 0, sizeof (struct static_ipv6));
2421
2422 si->type = type;
2423 si->distance = distance;
2424
2425 switch (type)
2426 {
2427 case STATIC_IPV6_GATEWAY:
2428 si->ipv6 = *gate;
2429 break;
2430 case STATIC_IPV6_IFNAME:
2431 si->ifname = XSTRDUP (0, ifname);
2432 break;
2433 case STATIC_IPV6_GATEWAY_IFNAME:
2434 si->ipv6 = *gate;
2435 si->ifname = XSTRDUP (0, ifname);
2436 break;
2437 }
2438
2439 /* Add new static route information to the tree with sort by
2440 distance value and gateway address. */
2441 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2442 {
2443 if (si->distance < cp->distance)
2444 break;
2445 if (si->distance > cp->distance)
2446 continue;
2447 }
2448
2449 /* Make linked list. */
2450 if (pp)
2451 pp->next = si;
2452 else
2453 rn->info = si;
2454 if (cp)
2455 cp->prev = si;
2456 si->prev = pp;
2457 si->next = cp;
2458
2459 /* Install into rib. */
2460 static_ipv6_install (p, si);
2461
2462 return 1;
2463}
2464
2465/* Delete static route from static route configuration. */
2466int
2467static_ipv6_delete (struct prefix_ipv6 *p, u_char type, struct in6_addr *gate,
2468 char *ifname, u_char distance, int table)
2469{
2470 struct route_node *rn;
2471 struct static_ipv6 *si;
2472
2473 /* Lookup static route prefix. */
2474 rn = route_node_lookup (static_table_ipv6, (struct prefix *) p);
2475 if (! rn)
2476 return 0;
2477
2478 /* Find same static route is the tree */
2479 for (si = rn->info; si; si = si->next)
2480 if (distance == si->distance
2481 && type == si->type
2482 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2483 && (! ifname || strcmp (ifname, si->ifname) == 0))
2484 break;
2485
2486 /* Can't find static route. */
2487 if (! si)
2488 {
2489 route_unlock_node (rn);
2490 return 0;
2491 }
2492
2493 /* Install into rib. */
2494 static_ipv6_uninstall (p, si);
2495
2496 /* Unlink static route from linked list. */
2497 if (si->prev)
2498 si->prev->next = si->next;
2499 else
2500 rn->info = si->next;
2501 if (si->next)
2502 si->next->prev = si->prev;
2503
2504 /* Free static route configuration. */
2505 XFREE (MTYPE_STATIC_IPV6, si);
2506
2507 return 1;
2508}
2509
2510/* General fucntion for IPv6 static route. */
2511int
2512static_ipv6_func (struct vty *vty, int add_cmd, char *dest_str,
2513 char *gate_str, char *ifname, char *distance_str)
2514{
2515 int ret;
2516 u_char distance;
2517 struct prefix_ipv6 p;
2518 struct in6_addr *gate = NULL;
2519 struct in6_addr gate_addr;
2520 u_char type = 0;
2521 int table = rtm_table_default;
2522
2523 ret = str2prefix_ipv6 (dest_str, &p);
2524 if (ret <= 0)
2525 {
2526 vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
2527 return CMD_WARNING;
2528 }
2529
2530 /* Apply mask for given prefix. */
2531 apply_mask_ipv6 (&p);
2532
2533 /* Administrative distance. */
2534 if (distance_str)
2535 distance = atoi (distance_str);
2536 else
2537 distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
2538
2539 /* When gateway is valid IPv6 addrees, then gate is treated as
2540 nexthop address other case gate is treated as interface name. */
2541 ret = inet_pton (AF_INET6, gate_str, &gate_addr);
2542
2543 if (ifname)
2544 {
2545 /* When ifname is specified. It must be come with gateway
2546 address. */
2547 if (ret != 1)
2548 {
2549 vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
2550 return CMD_WARNING;
2551 }
2552 type = STATIC_IPV6_GATEWAY_IFNAME;
2553 gate = &gate_addr;
2554 }
2555 else
2556 {
2557 if (ret == 1)
2558 {
2559 type = STATIC_IPV6_GATEWAY;
2560 gate = &gate_addr;
2561 }
2562 else
2563 {
2564 type = STATIC_IPV6_IFNAME;
2565 ifname = gate_str;
2566 }
2567 }
2568
2569 if (add_cmd)
2570 static_ipv6_add (&p, type, gate, ifname, distance, table);
2571 else
2572 static_ipv6_delete (&p, type, gate, ifname, distance, table);
2573
2574 return CMD_SUCCESS;
2575}
2576
2577/* Write IPv6 static route configuration. */
2578int
2579static_ipv6_write (struct vty *vty)
2580{
2581 struct route_node *rn;
2582 struct static_ipv6 *si;
2583 int write;
2584 char buf[BUFSIZ];
2585
2586 write = 0;
2587
2588 for (rn = route_top (static_table_ipv6); rn; rn = route_next (rn))
2589 for (si = rn->info; si; si = si->next)
2590 {
2591 vty_out (vty, "ipv6 route %s/%d",
2592 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
2593 rn->p.prefixlen);
2594
2595 switch (si->type)
2596 {
2597 case STATIC_IPV6_GATEWAY:
2598 vty_out (vty, " %s", inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ));
2599 break;
2600 case STATIC_IPV6_IFNAME:
2601 vty_out (vty, " %s", si->ifname);
2602 break;
2603 case STATIC_IPV6_GATEWAY_IFNAME:
2604 vty_out (vty, " %s %s",
2605 inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ), si->ifname);
2606 break;
2607 }
2608
2609 if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
2610 vty_out (vty, " %d", si->distance);
2611 vty_out (vty, "%s", VTY_NEWLINE);
2612
2613 write = 1;
2614 }
2615 return write;
2616}
2617
2618DEFUN (ipv6_route,
2619 ipv6_route_cmd,
2620 "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)",
2621 IP_STR
2622 "Establish static routes\n"
2623 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2624 "IPv6 gateway address\n"
2625 "IPv6 gateway interface name\n")
2626{
2627 return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL);
2628}
2629
2630DEFUN (ipv6_route_ifname,
2631 ipv6_route_ifname_cmd,
2632 "ipv6 route X:X::X:X/M X:X::X:X INTERFACE",
2633 IP_STR
2634 "Establish static routes\n"
2635 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2636 "IPv6 gateway address\n"
2637 "IPv6 gateway interface name\n")
2638{
2639 return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL);
2640}
2641
2642DEFUN (ipv6_route_pref,
2643 ipv6_route_pref_cmd,
2644 "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>",
2645 IP_STR
2646 "Establish static routes\n"
2647 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2648 "IPv6 gateway address\n"
2649 "IPv6 gateway interface name\n"
2650 "Distance value for this prefix\n")
2651{
2652 return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2]);
2653}
2654
2655DEFUN (ipv6_route_ifname_pref,
2656 ipv6_route_ifname_pref_cmd,
2657 "ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>",
2658 IP_STR
2659 "Establish static routes\n"
2660 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2661 "IPv6 gateway address\n"
2662 "IPv6 gateway interface name\n"
2663 "Distance value for this prefix\n")
2664{
2665 return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3]);
2666}
2667
2668DEFUN (no_ipv6_route,
2669 no_ipv6_route_cmd,
2670 "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)",
2671 NO_STR
2672 IP_STR
2673 "Establish static routes\n"
2674 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2675 "IPv6 gateway address\n"
2676 "IPv6 gateway interface name\n")
2677{
2678 return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL);
2679}
2680
2681DEFUN (no_ipv6_route_ifname,
2682 no_ipv6_route_ifname_cmd,
2683 "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE",
2684 NO_STR
2685 IP_STR
2686 "Establish static routes\n"
2687 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2688 "IPv6 gateway address\n"
2689 "IPv6 gateway interface name\n")
2690{
2691 return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL);
2692}
2693
2694DEFUN (no_ipv6_route_pref,
2695 no_ipv6_route_pref_cmd,
2696 "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>",
2697 NO_STR
2698 IP_STR
2699 "Establish static routes\n"
2700 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2701 "IPv6 gateway address\n"
2702 "IPv6 gateway interface name\n"
2703 "Distance value for this prefix\n")
2704{
2705 return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2]);
2706}
2707
2708DEFUN (no_ipv6_route_ifname_pref,
2709 no_ipv6_route_ifname_pref_cmd,
2710 "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>",
2711 NO_STR
2712 IP_STR
2713 "Establish static routes\n"
2714 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2715 "IPv6 gateway address\n"
2716 "IPv6 gateway interface name\n"
2717 "Distance value for this prefix\n")
2718{
2719 return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3]);
2720}
2721
2722/* New RIB. Detailed information for IPv4 route. */
2723void
2724vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn)
2725{
2726 struct rib *rib;
2727 struct nexthop *nexthop;
2728 char buf[BUFSIZ];
2729
2730 for (rib = rn->info; rib; rib = rib->next)
2731 {
2732 vty_out (vty, "Routing entry for %s/%d%s",
2733 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
2734 rn->p.prefixlen,
2735 VTY_NEWLINE);
2736 vty_out (vty, " Known via \"%s\"", route_info[rib->type].str);
2737 vty_out (vty, ", distance %d, metric %d", rib->distance, rib->metric);
2738 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2739 vty_out (vty, ", best");
2740 if (rib->refcnt)
2741 vty_out (vty, ", refcnt %ld", rib->refcnt);
2742 vty_out (vty, "%s", VTY_NEWLINE);
2743
2744#define ONE_DAY_SECOND 60*60*24
2745#define ONE_WEEK_SECOND 60*60*24*7
2746 if (rib->type == ZEBRA_ROUTE_RIPNG
2747 || rib->type == ZEBRA_ROUTE_OSPF6
2748 || rib->type == ZEBRA_ROUTE_ISIS
2749 || rib->type == ZEBRA_ROUTE_BGP)
2750 {
2751 time_t uptime;
2752 struct tm *tm;
2753
2754 uptime = time (NULL);
2755 uptime -= rib->uptime;
2756 tm = gmtime (&uptime);
2757
2758 vty_out (vty, " Last update ");
2759
2760 if (uptime < ONE_DAY_SECOND)
2761 vty_out (vty, "%02d:%02d:%02d",
2762 tm->tm_hour, tm->tm_min, tm->tm_sec);
2763 else if (uptime < ONE_WEEK_SECOND)
2764 vty_out (vty, "%dd%02dh%02dm",
2765 tm->tm_yday, tm->tm_hour, tm->tm_min);
2766 else
2767 vty_out (vty, "%02dw%dd%02dh",
2768 tm->tm_yday/7,
2769 tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
2770 vty_out (vty, " ago%s", VTY_NEWLINE);
2771 }
2772
2773 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2774 {
2775 vty_out (vty, " %c",
2776 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
2777
2778 switch (nexthop->type)
2779 {
2780 case NEXTHOP_TYPE_IPV6:
2781 case NEXTHOP_TYPE_IPV6_IFINDEX:
2782 case NEXTHOP_TYPE_IPV6_IFNAME:
2783 vty_out (vty, " %s",
2784 inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
2785 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
2786 vty_out (vty, ", %s", nexthop->ifname);
2787 else if (nexthop->ifindex)
2788 vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex));
2789 break;
2790 case NEXTHOP_TYPE_IFINDEX:
2791 vty_out (vty, " directly connected, %s",
2792 ifindex2ifname (nexthop->ifindex));
2793 break;
2794 case NEXTHOP_TYPE_IFNAME:
2795 vty_out (vty, " directly connected, %s",
2796 nexthop->ifname);
2797 break;
2798 default:
2799 break;
2800 }
2801 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
2802 vty_out (vty, " inactive");
2803
2804 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
2805 {
2806 vty_out (vty, " (recursive");
2807
2808 switch (nexthop->rtype)
2809 {
2810 case NEXTHOP_TYPE_IPV6:
2811 case NEXTHOP_TYPE_IPV6_IFINDEX:
2812 case NEXTHOP_TYPE_IPV6_IFNAME:
2813 vty_out (vty, " via %s)",
2814 inet_ntop (AF_INET6, &nexthop->rgate.ipv6,
2815 buf, BUFSIZ));
2816 if (nexthop->rifindex)
2817 vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
2818 break;
2819 case NEXTHOP_TYPE_IFINDEX:
2820 case NEXTHOP_TYPE_IFNAME:
2821 vty_out (vty, " is directly connected, %s)",
2822 ifindex2ifname (nexthop->rifindex));
2823 break;
2824 default:
2825 break;
2826 }
2827 }
2828 vty_out (vty, "%s", VTY_NEWLINE);
2829 }
2830 vty_out (vty, "%s", VTY_NEWLINE);
2831 }
2832}
2833
2834void
2835vty_show_ipv6_route (struct vty *vty, struct route_node *rn,
2836 struct rib *rib)
2837{
2838 struct nexthop *nexthop;
2839 int len = 0;
2840 char buf[BUFSIZ];
2841
2842 /* Nexthop information. */
2843 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2844 {
2845 if (nexthop == rib->nexthop)
2846 {
2847 /* Prefix information. */
2848 len = vty_out (vty, "%c%c%c %s/%d",
2849 route_info[rib->type].c,
2850 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)
2851 ? '>' : ' ',
2852 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
2853 ? '*' : ' ',
2854 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
2855 rn->p.prefixlen);
2856
2857 /* Distance and metric display. */
2858 if (rib->type != ZEBRA_ROUTE_CONNECT
2859 && rib->type != ZEBRA_ROUTE_KERNEL)
2860 len += vty_out (vty, " [%d/%d]", rib->distance,
2861 rib->metric);
2862 }
2863 else
2864 vty_out (vty, " %c%*c",
2865 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
2866 ? '*' : ' ',
2867 len - 3, ' ');
2868
2869 switch (nexthop->type)
2870 {
2871 case NEXTHOP_TYPE_IPV6:
2872 case NEXTHOP_TYPE_IPV6_IFINDEX:
2873 case NEXTHOP_TYPE_IPV6_IFNAME:
2874 vty_out (vty, " via %s",
2875 inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
2876 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
2877 vty_out (vty, ", %s", nexthop->ifname);
2878 else if (nexthop->ifindex)
2879 vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex));
2880 break;
2881 case NEXTHOP_TYPE_IFINDEX:
2882 vty_out (vty, " is directly connected, %s",
2883 ifindex2ifname (nexthop->ifindex));
2884 break;
2885 case NEXTHOP_TYPE_IFNAME:
2886 vty_out (vty, " is directly connected, %s",
2887 nexthop->ifname);
2888 break;
2889 default:
2890 break;
2891 }
2892 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
2893 vty_out (vty, " inactive");
2894
2895 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
2896 {
2897 vty_out (vty, " (recursive");
2898
2899 switch (nexthop->rtype)
2900 {
2901 case NEXTHOP_TYPE_IPV6:
2902 case NEXTHOP_TYPE_IPV6_IFINDEX:
2903 case NEXTHOP_TYPE_IPV6_IFNAME:
2904 vty_out (vty, " via %s)",
2905 inet_ntop (AF_INET6, &nexthop->rgate.ipv6,
2906 buf, BUFSIZ));
2907 if (nexthop->rifindex)
2908 vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
2909 break;
2910 case NEXTHOP_TYPE_IFINDEX:
2911 case NEXTHOP_TYPE_IFNAME:
2912 vty_out (vty, " is directly connected, %s)",
2913 ifindex2ifname (nexthop->rifindex));
2914 break;
2915 default:
2916 break;
2917 }
2918 }
2919
2920 if (rib->type == ZEBRA_ROUTE_RIPNG
2921 || rib->type == ZEBRA_ROUTE_OSPF6
2922 || rib->type == ZEBRA_ROUTE_ISIS
2923 || rib->type == ZEBRA_ROUTE_BGP)
2924 {
2925 time_t uptime;
2926 struct tm *tm;
2927
2928 uptime = time (NULL);
2929 uptime -= rib->uptime;
2930 tm = gmtime (&uptime);
2931
2932#define ONE_DAY_SECOND 60*60*24
2933#define ONE_WEEK_SECOND 60*60*24*7
2934
2935 if (uptime < ONE_DAY_SECOND)
2936 vty_out (vty, ", %02d:%02d:%02d",
2937 tm->tm_hour, tm->tm_min, tm->tm_sec);
2938 else if (uptime < ONE_WEEK_SECOND)
2939 vty_out (vty, ", %dd%02dh%02dm",
2940 tm->tm_yday, tm->tm_hour, tm->tm_min);
2941 else
2942 vty_out (vty, ", %02dw%dd%02dh",
2943 tm->tm_yday/7,
2944 tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
2945 }
2946 vty_out (vty, "%s", VTY_NEWLINE);
2947 }
2948}
2949
2950#define SHOW_ROUTE_V6_HEADER "Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS,%s B - BGP, * - FIB route.%s%s"
2951
2952DEFUN (show_ipv6_route,
2953 show_ipv6_route_cmd,
2954 "show ipv6 route",
2955 SHOW_STR
2956 IP_STR
2957 "IPv6 routing table\n")
2958{
2959 struct route_node *rn;
2960 struct rib *rib;
2961 int first = 1;
2962
2963 /* Show all IPv6 route. */
2964 for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
2965 for (rib = rn->info; rib; rib = rib->next)
2966 {
2967 if (first)
2968 {
2969 vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
2970 first = 0;
2971 }
2972 vty_show_ipv6_route (vty, rn, rib);
2973 }
2974 return CMD_SUCCESS;
2975}
2976
2977DEFUN (show_ipv6_route_prefix_longer,
2978 show_ipv6_route_prefix_longer_cmd,
2979 "show ipv6 route X:X::X:X/M longer-prefixes",
2980 SHOW_STR
2981 IP_STR
2982 "IPv6 routing table\n"
2983 "IPv6 prefix\n"
2984 "Show route matching the specified Network/Mask pair only\n")
2985{
2986 struct route_node *rn;
2987 struct rib *rib;
2988 struct prefix p;
2989 int ret;
2990 int first = 1;
2991
2992 ret = str2prefix (argv[0], &p);
2993 if (! ret)
2994 {
2995 vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
2996 return CMD_WARNING;
2997 }
2998
2999 /* Show matched type IPv6 routes. */
3000 for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
3001 for (rib = rn->info; rib; rib = rib->next)
3002 if (prefix_match (&p, &rn->p))
3003 {
3004 if (first)
3005 {
3006 vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
3007 first = 0;
3008 }
3009 vty_show_ipv6_route (vty, rn, rib);
3010 }
3011 return CMD_SUCCESS;
3012}
3013
3014DEFUN (show_ipv6_route_protocol,
3015 show_ipv6_route_protocol_cmd,
3016 "show ipv6 route (bgp|connected|kernel|ospf6|isis|ripng|static)",
3017 SHOW_STR
3018 IP_STR
3019 "IP routing table\n"
3020 "Border Gateway Protocol (BGP)\n"
3021 "Connected\n"
3022 "Kernel\n"
3023 "Open Shortest Path First (OSPFv3)\n"
3024 "ISO IS-IS (ISIS)\n"
3025 "Routing Information Protocol (RIPng)\n"
3026 "Static routes\n")
3027{
3028 int type;
3029 struct route_node *rn;
3030 struct rib *rib;
3031 int first = 1;
3032
3033 if (strncmp (argv[0], "b", 1) == 0)
3034 type = ZEBRA_ROUTE_BGP;
3035 else if (strncmp (argv[0], "c", 1) == 0)
3036 type = ZEBRA_ROUTE_CONNECT;
3037 else if (strncmp (argv[0], "k", 1) ==0)
3038 type = ZEBRA_ROUTE_KERNEL;
3039 else if (strncmp (argv[0], "o", 1) == 0)
3040 type = ZEBRA_ROUTE_OSPF6;
3041 else if (strncmp (argv[0], "i", 1) == 0)
3042 type = ZEBRA_ROUTE_ISIS;
3043 else if (strncmp (argv[0], "r", 1) == 0)
3044 type = ZEBRA_ROUTE_RIPNG;
3045 else if (strncmp (argv[0], "s", 1) == 0)
3046 type = ZEBRA_ROUTE_STATIC;
3047 else
3048 {
3049 vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
3050 return CMD_WARNING;
3051 }
3052
3053 /* Show matched type IPv6 routes. */
3054 for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
3055 for (rib = rn->info; rib; rib = rib->next)
3056 if (rib->type == type)
3057 {
3058 if (first)
3059 {
3060 vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
3061 first = 0;
3062 }
3063 vty_show_ipv6_route (vty, rn, rib);
3064 }
3065 return CMD_SUCCESS;
3066}
3067
3068
3069DEFUN (show_ipv6_route_addr,
3070 show_ipv6_route_addr_cmd,
3071 "show ipv6 route X:X::X:X",
3072 SHOW_STR
3073 IP_STR
3074 "IPv6 routing table\n"
3075 "IPv6 Address\n")
3076{
3077 int ret;
3078 struct prefix_ipv6 p;
3079 struct route_node *rn;
3080
3081 ret = str2prefix_ipv6 (argv[0], &p);
3082 if (ret <= 0)
3083 {
3084 vty_out (vty, "Malformed IPv6 address%s", VTY_NEWLINE);
3085 return CMD_WARNING;
3086 }
3087
3088 rn = route_node_match (rib_table_ipv6, (struct prefix *) &p);
3089 if (! rn)
3090 {
3091 vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
3092 return CMD_WARNING;
3093 }
3094
3095 vty_show_ipv6_route_detail (vty, rn);
3096
3097 route_unlock_node (rn);
3098
3099 return CMD_SUCCESS;
3100}
3101
3102DEFUN (show_ipv6_route_prefix,
3103 show_ipv6_route_prefix_cmd,
3104 "show ipv6 route X:X::X:X/M",
3105 SHOW_STR
3106 IP_STR
3107 "IPv6 routing table\n"
3108 "IPv6 prefix\n")
3109{
3110 int ret;
3111 struct prefix_ipv6 p;
3112 struct route_node *rn;
3113
3114 ret = str2prefix_ipv6 (argv[0], &p);
3115 if (ret <= 0)
3116 {
3117 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
3118 return CMD_WARNING;
3119 }
3120
3121 rn = route_node_match (rib_table_ipv6, (struct prefix *) &p);
3122 if (! rn || rn->p.prefixlen != p.prefixlen)
3123 {
3124 vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
3125 return CMD_WARNING;
3126 }
3127
3128 vty_show_ipv6_route_detail (vty, rn);
3129
3130 route_unlock_node (rn);
3131
3132 return CMD_SUCCESS;
3133}
3134#endif /* HAVE_IPV6 */
3135
3136/* RIB update function. */
3137void
3138rib_update ()
3139{
3140 struct route_node *rn;
3141
3142 for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
3143 /* Update reachability. */
3144 rib_process (rn, NULL);
3145
3146#ifdef HAVE_IPV6
3147 for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
3148 rib_process (rn, NULL);
3149#endif /* HAVE_IPV6 */
3150}
3151
3152/* Interface goes up. */
3153void
3154rib_if_up (struct interface *ifp)
3155{
3156 rib_update ();
3157}
3158
3159/* Interface goes down. */
3160void
3161rib_if_down (struct interface *ifp)
3162{
3163 rib_update ();
3164}
3165
3166/* Clean up routines. */
3167void
3168rib_weed_table (struct route_table *rib_table)
3169{
3170 struct route_node *rn;
3171 struct rib *rib;
3172 struct rib *next;
3173
3174 for (rn = route_top (rib_table); rn; rn = route_next (rn))
3175 for (rib = rn->info; rib; rib = next)
3176 {
3177 next = rib->next;
3178
3179 if (rib->table != rtm_table_default &&
3180 rib->table != RT_TABLE_MAIN)
3181 {
3182 rib_delnode (rn, rib);
3183 newrib_free (rib);
3184 route_unlock_node (rn);
3185 }
3186 }
3187}
3188
3189/* Delete all routes from unmanaged tables. */
3190void
3191rib_weed_tables ()
3192{
3193 rib_weed_table (rib_table_ipv4);
3194#ifdef HAVE_IPV6
3195 rib_weed_table (rib_table_ipv6);
3196#endif /* HAVE_IPV6 */
3197}
3198
3199void
3200rib_sweep_table (struct route_table *rib_table)
3201{
3202 struct route_node *rn;
3203 struct rib *rib;
3204 struct rib *next;
3205 int ret = 0;
3206
3207 for (rn = route_top (rib_table); rn; rn = route_next (rn))
3208 for (rib = rn->info; rib; rib = next)
3209 {
3210 next = rib->next;
3211
3212 if ((rib->type == ZEBRA_ROUTE_KERNEL) &&
3213 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3214 {
3215 ret = rib_uninstall_kernel (rn, rib);
3216
3217 if (! ret)
3218 {
3219 rib_delnode (rn, rib);
3220 newrib_free (rib);
3221 route_unlock_node (rn);
3222 }
3223 }
3224 }
3225}
3226
3227void
3228rib_sweep_route ()
3229{
3230 rib_sweep_table (rib_table_ipv4);
3231#ifdef HAVE_IPV6
3232 rib_sweep_table (rib_table_ipv6);
3233#endif /* HAVE_IPV6 */
3234}
3235
3236/* Close rib when zebra terminates. */
3237void
3238rib_close ()
3239{
3240 rib_close_ipv4 ();
3241#ifdef HAVE_IPV6
3242 rib_close_ipv6 ();
3243#endif /* HAVE_IPV6 */
3244}
3245
3246/* Static ip route configuration write function. */
3247int
3248config_write_ip (struct vty *vty)
3249{
3250 int write = 0;
3251
3252 write += static_ipv4_write (vty);
3253#ifdef HAVE_IPV6
3254 write += static_ipv6_write (vty);
3255#endif /* HAVE_IPV6 */
3256
3257 return write;
3258}
3259
3260/* IP node for static routes. */
3261struct cmd_node ip_node =
3262{
3263 IP_NODE,
3264 "", /* This node has no interface. */
3265 1
3266};
3267
3268/* Routing information base initialize. */
3269void
3270rib_init ()
3271{
3272 install_node (&ip_node, config_write_ip);
3273
3274 rib_table_ipv4 = route_table_init ();
3275 static_table_ipv4 = route_table_init ();
3276
3277 install_element (VIEW_NODE, &show_ip_route_cmd);
3278 install_element (VIEW_NODE, &show_ip_route_addr_cmd);
3279 install_element (VIEW_NODE, &show_ip_route_prefix_cmd);
3280 install_element (VIEW_NODE, &show_ip_route_prefix_longer_cmd);
3281 install_element (VIEW_NODE, &show_ip_route_protocol_cmd);
3282 install_element (VIEW_NODE, &show_ip_route_supernets_cmd);
3283 install_element (ENABLE_NODE, &show_ip_route_cmd);
3284 install_element (ENABLE_NODE, &show_ip_route_addr_cmd);
3285 install_element (ENABLE_NODE, &show_ip_route_prefix_cmd);
3286 install_element (ENABLE_NODE, &show_ip_route_prefix_longer_cmd);
3287 install_element (ENABLE_NODE, &show_ip_route_protocol_cmd);
3288 install_element (ENABLE_NODE, &show_ip_route_supernets_cmd);
3289 install_element (CONFIG_NODE, &ip_route_cmd);
3290 install_element (CONFIG_NODE, &ip_route_mask_cmd);
3291 install_element (CONFIG_NODE, &no_ip_route_cmd);
3292 install_element (CONFIG_NODE, &no_ip_route_mask_cmd);
3293 install_element (CONFIG_NODE, &ip_route_pref_cmd);
3294 install_element (CONFIG_NODE, &ip_route_mask_pref_cmd);
3295 install_element (CONFIG_NODE, &no_ip_route_pref_cmd);
3296 install_element (CONFIG_NODE, &no_ip_route_mask_pref_cmd);
3297
3298#ifdef HAVE_IPV6
3299 rib_table_ipv6 = route_table_init ();
3300 static_table_ipv6 = route_table_init ();
3301
3302 install_element (CONFIG_NODE, &ipv6_route_cmd);
3303 install_element (CONFIG_NODE, &ipv6_route_ifname_cmd);
3304 install_element (CONFIG_NODE, &no_ipv6_route_cmd);
3305 install_element (CONFIG_NODE, &no_ipv6_route_ifname_cmd);
3306 install_element (CONFIG_NODE, &ipv6_route_pref_cmd);
3307 install_element (CONFIG_NODE, &ipv6_route_ifname_pref_cmd);
3308 install_element (CONFIG_NODE, &no_ipv6_route_pref_cmd);
3309 install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_cmd);
3310 install_element (VIEW_NODE, &show_ipv6_route_cmd);
3311 install_element (VIEW_NODE, &show_ipv6_route_protocol_cmd);
3312 install_element (VIEW_NODE, &show_ipv6_route_addr_cmd);
3313 install_element (VIEW_NODE, &show_ipv6_route_prefix_cmd);
3314 install_element (VIEW_NODE, &show_ipv6_route_prefix_longer_cmd);
3315 install_element (ENABLE_NODE, &show_ipv6_route_cmd);
3316 install_element (ENABLE_NODE, &show_ipv6_route_protocol_cmd);
3317 install_element (ENABLE_NODE, &show_ipv6_route_addr_cmd);
3318 install_element (ENABLE_NODE, &show_ipv6_route_prefix_cmd);
3319 install_element (ENABLE_NODE, &show_ipv6_route_prefix_longer_cmd);
3320#endif /* HAVE_IPV6 */
3321}