summaryrefslogtreecommitdiff
path: root/isisd/modified/rib.c
diff options
context:
space:
mode:
Diffstat (limited to 'isisd/modified/rib.c')
-rw-r--r--isisd/modified/rib.c3321
1 files changed, 0 insertions, 3321 deletions
diff --git a/isisd/modified/rib.c b/isisd/modified/rib.c
deleted file mode 100644
index 39a7690b..00000000
--- a/isisd/modified/rib.c
+++ /dev/null
@@ -1,3321 +0,0 @@
-/* Routing Information Base.
- * Copyright (C) 1997, 98, 99, 2001 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-#include <zebra.h>
-
-#include "prefix.h"
-#include "table.h"
-#include "memory.h"
-#include "vty.h"
-#include "str.h"
-#include "command.h"
-#include "linklist.h"
-#include "if.h"
-#include "log.h"
-#include "sockunion.h"
-
-#include "zebra/rib.h"
-#include "zebra/rt.h"
-#include "zebra/zserv.h"
-#include "zebra/redistribute.h"
-#include "zebra/debug.h"
-
-/* Routing information base and static table for IPv4. */
-struct route_table *rib_table_ipv4;
-struct route_table *static_table_ipv4;
-
-/* Routing information base and static table for IPv6. */
-#ifdef HAVE_IPV6
-struct route_table *rib_table_ipv6;
-struct route_table *static_table_ipv6;
-#endif /* HAVE_IPV6 */
-
-/* Default rtm_table for all clients */
-extern int rtm_table_default;
-
-/* Each route type's string and default distance value. */
-struct
-{
- int key;
- char c;
- char *str;
- int distance;
-} route_info[] =
-{
- {ZEBRA_ROUTE_SYSTEM, 'X', "system", 0},
- {ZEBRA_ROUTE_KERNEL, 'K', "kernel", 0},
- {ZEBRA_ROUTE_CONNECT, 'C', "connected", 0},
- {ZEBRA_ROUTE_STATIC, 'S', "static", 1},
- {ZEBRA_ROUTE_RIP, 'R', "rip", 120},
- {ZEBRA_ROUTE_RIPNG, 'R', "ripng", 120},
- {ZEBRA_ROUTE_OSPF, 'O', "ospf", 110},
- {ZEBRA_ROUTE_OSPF6, 'O', "ospf6", 110},
- {ZEBRA_ROUTE_ISIS, 'I', "isis", 115},
- {ZEBRA_ROUTE_BGP, 'B', "bgp", 20 /* IBGP is 200. */}
-};
-
-/* Add nexthop to the end of the list. */
-void
-nexthop_add (struct rib *rib, struct nexthop *nexthop)
-{
- struct nexthop *last;
-
- for (last = rib->nexthop; last && last->next; last = last->next)
- ;
- if (last)
- last->next = nexthop;
- else
- rib->nexthop = nexthop;
- nexthop->prev = last;
-
- rib->nexthop_num++;
-}
-
-/* Delete specified nexthop from the list. */
-void
-nexthop_delete (struct rib *rib, struct nexthop *nexthop)
-{
- if (nexthop->next)
- nexthop->next->prev = nexthop->prev;
- if (nexthop->prev)
- nexthop->prev->next = nexthop->next;
- else
- rib->nexthop = nexthop->next;
- rib->nexthop_num--;
-}
-
-/* Free nexthop. */
-void
-nexthop_free (struct nexthop *nexthop)
-{
- if (nexthop->type == NEXTHOP_TYPE_IFNAME && nexthop->ifname)
- free (nexthop->ifname);
- XFREE (MTYPE_NEXTHOP, nexthop);
-}
-
-struct nexthop *
-nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
-{
- struct nexthop *nexthop;
-
- nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
- memset (nexthop, 0, sizeof (struct nexthop));
- nexthop->type = NEXTHOP_TYPE_IFINDEX;
- nexthop->ifindex = ifindex;
-
- nexthop_add (rib, nexthop);
-
- return nexthop;
-}
-
-struct nexthop *
-nexthop_ifname_add (struct rib *rib, char *ifname)
-{
- struct nexthop *nexthop;
-
- nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
- memset (nexthop, 0, sizeof (struct nexthop));
- nexthop->type = NEXTHOP_TYPE_IFNAME;
- nexthop->ifname = strdup (ifname);
-
- nexthop_add (rib, nexthop);
-
- return nexthop;
-}
-
-struct nexthop *
-nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4)
-{
- struct nexthop *nexthop;
-
- nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
- memset (nexthop, 0, sizeof (struct nexthop));
- nexthop->type = NEXTHOP_TYPE_IPV4;
- nexthop->gate.ipv4 = *ipv4;
-
- nexthop_add (rib, nexthop);
-
- return nexthop;
-}
-
-struct nexthop *
-nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
- unsigned int ifindex)
-{
- struct nexthop *nexthop;
-
- nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
- memset (nexthop, 0, sizeof (struct nexthop));
- nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
- nexthop->gate.ipv4 = *ipv4;
- nexthop->ifindex = ifindex;
-
- nexthop_add (rib, nexthop);
-
- return nexthop;
-}
-
-#ifdef HAVE_IPV6
-struct nexthop *
-nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
-{
- struct nexthop *nexthop;
-
- nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
- memset (nexthop, 0, sizeof (struct nexthop));
- nexthop->type = NEXTHOP_TYPE_IPV6;
- nexthop->gate.ipv6 = *ipv6;
-
- nexthop_add (rib, nexthop);
-
- return nexthop;
-}
-
-struct nexthop *
-nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
- char *ifname)
-{
- struct nexthop *nexthop;
-
- nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
- memset (nexthop, 0, sizeof (struct nexthop));
- nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
- nexthop->gate.ipv6 = *ipv6;
- nexthop->ifname = XSTRDUP (0, ifname);
-
- nexthop_add (rib, nexthop);
-
- return nexthop;
-}
-
-struct nexthop *
-nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
- unsigned int ifindex)
-{
- struct nexthop *nexthop;
-
- nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
- memset (nexthop, 0, sizeof (struct nexthop));
- nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
- nexthop->gate.ipv6 = *ipv6;
- nexthop->ifindex = ifindex;
-
- nexthop_add (rib, nexthop);
-
- return nexthop;
-}
-#endif /* HAVE_IPV6 */
-
-/* If force flag is not set, do not modify falgs at all for uninstall
- the route from FIB. */
-int
-nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
- struct route_node *top)
-{
- struct prefix_ipv4 p;
- struct route_node *rn;
- struct rib *match;
- struct nexthop *newhop;
-
- if (nexthop->type == NEXTHOP_TYPE_IPV4)
- nexthop->ifindex = 0;
-
- if (set)
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
-
- /* Make lookup prefix. */
- memset (&p, 0, sizeof (struct prefix_ipv4));
- p.family = AF_INET;
- p.prefixlen = IPV4_MAX_PREFIXLEN;
- p.prefix = nexthop->gate.ipv4;
-
- rn = route_node_match (rib_table_ipv4, (struct prefix *) &p);
- while (rn)
- {
- route_unlock_node (rn);
-
- /* If lookup self prefix return immidiately. */
- if (rn == top)
- return 0;
-
- /* Pick up selected route. */
- for (match = rn->info; match; match = match->next)
- if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
- break;
-
- /* If there is no selected route or matched route is EGP, go up
- tree. */
- if (! match
- || match->type == ZEBRA_ROUTE_BGP)
- {
- do {
- rn = rn->parent;
- } while (rn && rn->info == NULL);
- if (rn)
- route_lock_node (rn);
- }
- else
- {
- if (match->type == ZEBRA_ROUTE_CONNECT)
- {
- /* Directly point connected route. */
- newhop = match->nexthop;
- if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
- nexthop->ifindex = newhop->ifindex;
-
- return 1;
- }
- else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
- {
- for (newhop = match->nexthop; newhop; newhop = newhop->next)
- if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
- && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
- {
- if (set)
- {
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
- nexthop->rtype = newhop->type;
- if (newhop->type == NEXTHOP_TYPE_IPV4 ||
- newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
- nexthop->rgate.ipv4 = newhop->gate.ipv4;
- if (newhop->type == NEXTHOP_TYPE_IFINDEX
- || newhop->type == NEXTHOP_TYPE_IFNAME
- || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
- nexthop->rifindex = newhop->ifindex;
- }
- return 1;
- }
- return 0;
- }
- else
- {
- return 0;
- }
- }
- }
- return 0;
-}
-
-#ifdef HAVE_IPV6
-/* If force flag is not set, do not modify falgs at all for uninstall
- the route from FIB. */
-int
-nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
- struct route_node *top)
-{
- struct prefix_ipv6 p;
- struct route_node *rn;
- struct rib *match;
- struct nexthop *newhop;
-
- if (nexthop->type == NEXTHOP_TYPE_IPV6)
- nexthop->ifindex = 0;
-
- if (set)
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
-
- /* Make lookup prefix. */
- memset (&p, 0, sizeof (struct prefix_ipv6));
- p.family = AF_INET6;
- p.prefixlen = IPV6_MAX_PREFIXLEN;
- p.prefix = nexthop->gate.ipv6;
-
- rn = route_node_match (rib_table_ipv6, (struct prefix *) &p);
- while (rn)
- {
- route_unlock_node (rn);
-
- /* If lookup self prefix return immidiately. */
- if (rn == top)
- return 0;
-
- /* Pick up selected route. */
- for (match = rn->info; match; match = match->next)
- if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
- break;
-
- /* If there is no selected route or matched route is EGP, go up
- tree. */
- if (! match
- || match->type == ZEBRA_ROUTE_BGP)
- {
- do {
- rn = rn->parent;
- } while (rn && rn->info == NULL);
- if (rn)
- route_lock_node (rn);
- }
- else
- {
- if (match->type == ZEBRA_ROUTE_CONNECT)
- {
- /* Directly point connected route. */
- newhop = match->nexthop;
-
- if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
- nexthop->ifindex = newhop->ifindex;
-
- return 1;
- }
- else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
- {
- for (newhop = match->nexthop; newhop; newhop = newhop->next)
- if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
- && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
- {
- if (set)
- {
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
- nexthop->rtype = newhop->type;
- if (newhop->type == NEXTHOP_TYPE_IPV6
- || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
- || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
- nexthop->rgate.ipv6 = newhop->gate.ipv6;
- if (newhop->type == NEXTHOP_TYPE_IFINDEX
- || newhop->type == NEXTHOP_TYPE_IFNAME
- || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
- || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
- nexthop->rifindex = newhop->ifindex;
- }
- return 1;
- }
- return 0;
- }
- else
- {
- return 0;
- }
- }
- }
- return 0;
-}
-#endif /* HAVE_IPV6 */
-
-struct rib *
-rib_match_ipv4 (struct in_addr addr)
-{
- struct prefix_ipv4 p;
- struct route_node *rn;
- struct rib *match;
- struct nexthop *newhop;
-
- memset (&p, 0, sizeof (struct prefix_ipv4));
- p.family = AF_INET;
- p.prefixlen = IPV4_MAX_PREFIXLEN;
- p.prefix = addr;
-
- rn = route_node_match (rib_table_ipv4, (struct prefix *) &p);
-
- while (rn)
- {
- route_unlock_node (rn);
-
- /* Pick up selected route. */
- for (match = rn->info; match; match = match->next)
- if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
- break;
-
- /* If there is no selected route or matched route is EGP, go up
- tree. */
- if (! match
- || match->type == ZEBRA_ROUTE_BGP)
- {
- do {
- rn = rn->parent;
- } while (rn && rn->info == NULL);
- if (rn)
- route_lock_node (rn);
- }
- else
- {
- if (match->type == ZEBRA_ROUTE_CONNECT)
- /* Directly point connected route. */
- return match;
- else
- {
- for (newhop = match->nexthop; newhop; newhop = newhop->next)
- if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
- return match;
- return NULL;
- }
- }
- }
- return NULL;
-}
-
-struct rib *
-rib_lookup_ipv4 (struct prefix_ipv4 *p)
-{
- struct route_node *rn;
- struct rib *match;
- struct nexthop *nexthop;
-
- rn = route_node_lookup (rib_table_ipv4, (struct prefix *) p);
-
- /* No route for this prefix. */
- if (! rn)
- return NULL;
-
- /* Unlock node. */
- route_unlock_node (rn);
-
- /* Pick up selected route. */
- for (match = rn->info; match; match = match->next)
- if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
- break;
-
- if (! match || match->type == ZEBRA_ROUTE_BGP)
- return NULL;
-
- if (match->type == ZEBRA_ROUTE_CONNECT)
- return match;
-
- for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
- return match;
-
- return NULL;
-}
-
-#ifdef HAVE_IPV6
-struct rib *
-rib_match_ipv6 (struct in6_addr *addr)
-{
- struct prefix_ipv6 p;
- struct route_node *rn;
- struct rib *match;
- struct nexthop *newhop;
-
- memset (&p, 0, sizeof (struct prefix_ipv6));
- p.family = AF_INET6;
- p.prefixlen = IPV6_MAX_PREFIXLEN;
- IPV6_ADDR_COPY (&p.prefix, addr);
-
- rn = route_node_match (rib_table_ipv6, (struct prefix *) &p);
-
- while (rn)
- {
- route_unlock_node (rn);
-
- /* Pick up selected route. */
- for (match = rn->info; match; match = match->next)
- if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
- break;
-
- /* If there is no selected route or matched route is EGP, go up
- tree. */
- if (! match
- || match->type == ZEBRA_ROUTE_BGP)
- {
- do {
- rn = rn->parent;
- } while (rn && rn->info == NULL);
- if (rn)
- route_lock_node (rn);
- }
- else
- {
- if (match->type == ZEBRA_ROUTE_CONNECT)
- /* Directly point connected route. */
- return match;
- else
- {
- for (newhop = match->nexthop; newhop; newhop = newhop->next)
- if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
- return match;
- return NULL;
- }
- }
- }
- return NULL;
-}
-#endif /* HAVE_IPV6 */
-
-int
-nexthop_active_check (struct route_node *rn, struct rib *rib,
- struct nexthop *nexthop, int set)
-{
- struct interface *ifp;
-
- switch (nexthop->type)
- {
- case NEXTHOP_TYPE_IFINDEX:
- ifp = if_lookup_by_index (nexthop->ifindex);
- if (ifp && if_is_up (ifp))
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- else
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- break;
- case NEXTHOP_TYPE_IFNAME:
- case NEXTHOP_TYPE_IPV6_IFNAME:
- ifp = if_lookup_by_name (nexthop->ifname);
- if (ifp && if_is_up (ifp))
- {
- if (set)
- nexthop->ifindex = ifp->ifindex;
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- }
- else
- {
- if (set)
- nexthop->ifindex = 0;
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- }
- break;
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- if (nexthop_active_ipv4 (rib, nexthop, set, rn))
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- else
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- break;
-#ifdef HAVE_IPV6
- case NEXTHOP_TYPE_IPV6:
- if (nexthop_active_ipv6 (rib, nexthop, set, rn))
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- else
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- break;
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
- {
- ifp = if_lookup_by_index (nexthop->ifindex);
- if (ifp && if_is_up (ifp))
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- else
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- }
- else
- {
- if (nexthop_active_ipv6 (rib, nexthop, set, rn))
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- else
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- }
- break;
-#endif /* HAVE_IPV6 */
- default:
- break;
- }
- return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
-}
-
-int
-nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
-{
- struct nexthop *nexthop;
- int active;
-
- rib->nexthop_active_num = 0;
- UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
-
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- {
- active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- rib->nexthop_active_num += nexthop_active_check (rn, rib, nexthop, set);
- if (active != CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
- }
- return rib->nexthop_active_num;
-}
-
-#define RIB_SYSTEM_ROUTE(R) \
- ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
-
-void
-newrib_free (struct rib *rib)
-{
- struct nexthop *nexthop;
- struct nexthop *next;
-
- for (nexthop = rib->nexthop; nexthop; nexthop = next)
- {
- next = nexthop->next;
- nexthop_free (nexthop);
- }
- XFREE (MTYPE_RIB, rib);
-}
-
-void
-rib_install_kernel (struct route_node *rn, struct rib *rib)
-{
- int ret = 0;
- struct nexthop *nexthop;
-
- switch (PREFIX_FAMILY (&rn->p))
- {
- case AF_INET:
- ret = kernel_add_ipv4 (&rn->p, rib);
- break;
-#ifdef HAVE_IPV6
- case AF_INET6:
- ret = kernel_add_ipv6 (&rn->p, rib);
- break;
-#endif /* HAVE_IPV6 */
- }
-
- if (ret < 0)
- {
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
- }
-}
-
-/* Uninstall the route from kernel. */
-int
-rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
-{
- int ret = 0;
- struct nexthop *nexthop;
-
- switch (PREFIX_FAMILY (&rn->p))
- {
- case AF_INET:
- ret = kernel_delete_ipv4 (&rn->p, rib);
- break;
-#ifdef HAVE_IPV6
- case AF_INET6:
- ret = kernel_delete_ipv6 (&rn->p, rib);
- break;
-#endif /* HAVE_IPV6 */
- }
-
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
-
- return ret;
-}
-
-/* Uninstall the route from kernel. */
-void
-rib_uninstall (struct route_node *rn, struct rib *rib)
-{
- if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
- {
- redistribute_delete (&rn->p, rib);
- if (! RIB_SYSTEM_ROUTE (rib))
- rib_uninstall_kernel (rn, rib);
- UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
- }
-}
-
-/* Core function for processing routing information base. */
-void
-rib_process (struct route_node *rn, struct rib *del)
-{
- struct rib *rib;
- struct rib *next;
- struct rib *fib = NULL;
- struct rib *select = NULL;
-
- for (rib = rn->info; rib; rib = next)
- {
- next = rib->next;
-
- /* Currently installed rib. */
- if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
- fib = rib;
-
- /* Skip unreachable nexthop. */
- if (! nexthop_active_update (rn, rib, 0))
- continue;
-
- /* Infinit distance. */
- if (rib->distance == DISTANCE_INFINITY)
- continue;
-
- /* Newly selected rib. */
- if (! select || rib->distance < select->distance
- || rib->type == ZEBRA_ROUTE_CONNECT)
- select = rib;
- }
-
- /* Deleted route check. */
- if (del && CHECK_FLAG (del->flags, ZEBRA_FLAG_SELECTED))
- fib = del;
-
- /* Same route is selected. */
- if (select && select == fib)
- {
- if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
- {
- redistribute_delete (&rn->p, select);
- if (! RIB_SYSTEM_ROUTE (select))
- rib_uninstall_kernel (rn, select);
-
- /* Set real nexthop. */
- nexthop_active_update (rn, select, 1);
-
- if (! RIB_SYSTEM_ROUTE (select))
- rib_install_kernel (rn, select);
- redistribute_add (&rn->p, select);
- }
- return;
- }
-
- /* Uninstall old rib from forwarding table. */
- if (fib)
- {
- redistribute_delete (&rn->p, fib);
- if (! RIB_SYSTEM_ROUTE (fib))
- rib_uninstall_kernel (rn, fib);
- UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
-
- /* Set real nexthop. */
- nexthop_active_update (rn, fib, 1);
- }
-
- /* Install new rib into forwarding table. */
- if (select)
- {
- /* Set real nexthop. */
- nexthop_active_update (rn, select, 1);
-
- if (! RIB_SYSTEM_ROUTE (select))
- rib_install_kernel (rn, select);
- SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
- redistribute_add (&rn->p, select);
- }
-}
-
-/* Add RIB to head of the route node. */
-void
-rib_addnode (struct route_node *rn, struct rib *rib)
-{
- struct rib *head;
-
- head = rn->info;
- if (head)
- head->prev = rib;
- rib->next = head;
- rn->info = rib;
-}
-
-void
-rib_delnode (struct route_node *rn, struct rib *rib)
-{
- if (rib->next)
- rib->next->prev = rib->prev;
- if (rib->prev)
- rib->prev->next = rib->next;
- else
- rn->info = rib->next;
-}
-
-int
-rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
- struct in_addr *gate, unsigned int ifindex, int table,
- u_int32_t metric, u_char distance)
-{
- struct rib *rib;
- struct rib *same = NULL;
- struct route_node *rn;
- struct nexthop *nexthop;
-
- /* Make it sure prefixlen is applied to the prefix. */
- apply_mask_ipv4 (p);
-
- /* Set default distance by route type. */
- if (distance == 0)
- {
- distance = route_info[type].distance;
-
- /* iBGP distance is 200. */
- if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
- distance = 200;
- }
-
- /* Lookup route node.*/
- rn = route_node_get (rib_table_ipv4, (struct prefix *) p);
-
- /* If same type of route are installed, treat it as a implicit
- withdraw. */
- for (rib = rn->info; rib; rib = rib->next)
- {
- if (rib->type == ZEBRA_ROUTE_CONNECT)
- {
- nexthop = rib->nexthop;
-
- /* Duplicate connected route comes in. */
- if (rib->type == type
- && (! table || rib->table == table)
- && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
- && nexthop->ifindex == ifindex)
- {
- rib->refcnt++;
- return 0 ;
- }
- }
- else if (rib->type == type
- && (! table || rib->table == table))
- {
- same = rib;
- rib_delnode (rn, same);
- route_unlock_node (rn);
- break;
- }
- }
-
- /* Allocate new rib structure. */
- rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
- memset (rib, 0, sizeof (struct rib));
- rib->type = type;
- rib->distance = distance;
- rib->flags = flags;
- rib->metric = metric;
- rib->table = table;
- rib->nexthop_num = 0;
- rib->uptime = time (NULL);
-
- /* Nexthop settings. */
- if (gate)
- {
- if (ifindex)
- nexthop_ipv4_ifindex_add (rib, gate, ifindex);
- else
- nexthop_ipv4_add (rib, gate);
- }
- else
- nexthop_ifindex_add (rib, ifindex);
-
- /* If this route is kernel route, set FIB flag to the route. */
- if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
-
- /* Link new rib to node.*/
- rib_addnode (rn, rib);
-
- /* Process this route node. */
- rib_process (rn, same);
-
- /* Free implicit route.*/
- if (same)
- newrib_free (same);
-
- return 0;
-}
-
-int
-rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
-{
- struct route_node *rn;
- struct rib *same;
- struct nexthop *nexthop;
-
- /* Make it sure prefixlen is applied to the prefix. */
- apply_mask_ipv4 (p);
-
- /* Set default distance by route type. */
- if (rib->distance == 0)
- {
- rib->distance = route_info[rib->type].distance;
-
- /* iBGP distance is 200. */
- if (rib->type == ZEBRA_ROUTE_BGP
- && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
- rib->distance = 200;
- }
-
- /* Lookup route node.*/
- rn = route_node_get (rib_table_ipv4, (struct prefix *) p);
-
- /* If same type of route are installed, treat it as a implicit
- withdraw. */
- for (same = rn->info; same; same = same->next)
- {
- if (same->type == rib->type && same->table == rib->table
- && same->type != ZEBRA_ROUTE_CONNECT)
- {
- rib_delnode (rn, same);
- route_unlock_node (rn);
- break;
- }
- }
-
- /* If this route is kernel route, set FIB flag to the route. */
- if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
-
- /* Link new rib to node.*/
- rib_addnode (rn, rib);
-
- /* Process this route node. */
- rib_process (rn, same);
-
- /* Free implicit route.*/
- if (same)
- newrib_free (same);
-
- return 0;
-}
-
-int
-rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
- struct in_addr *gate, unsigned int ifindex, int table)
-{
- struct route_node *rn;
- struct rib *rib;
- struct rib *fib = NULL;
- struct rib *same = NULL;
- struct nexthop *nexthop;
- char buf1[BUFSIZ];
- char buf2[BUFSIZ];
-
- /* Apply mask. */
- apply_mask_ipv4 (p);
-
- /* Lookup route node. */
- rn = route_node_lookup (rib_table_ipv4, (struct prefix *) p);
- if (! rn)
- {
- if (IS_ZEBRA_DEBUG_KERNEL)
- {
- if (gate)
- zlog_info ("route %s/%d via %s ifindex %d doesn't exist in rib",
- inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
- p->prefixlen,
- inet_ntop (AF_INET, gate, buf2, BUFSIZ),
- ifindex);
- else
- zlog_info ("route %s/%d ifindex %d doesn't exist in rib",
- inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
- p->prefixlen,
- ifindex);
- }
- return ZEBRA_ERR_RTNOEXIST;
- }
-
- /* Lookup same type route. */
- for (rib = rn->info; rib; rib = rib->next)
- {
- if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
- fib = rib;
-
- if (rib->type == ZEBRA_ROUTE_CONNECT)
- {
- nexthop = rib->nexthop;
-
- if (rib->type == type
- && (! table || rib->table == table)
- && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
- && nexthop->ifindex == ifindex)
- {
- if (rib->refcnt)
- {
- rib->refcnt--;
- route_unlock_node (rn);
- route_unlock_node (rn);
- return 0;
- }
- same = rib;
- break;
- }
- }
- else
- {
- if (rib->type == type
- && (!table || rib->table == table))
- {
- same = rib;
- break;
- }
- }
- }
-
- /* If same type of route can't be found and this message is from
- kernel. */
- if (! same)
- {
- if (fib && type == ZEBRA_ROUTE_KERNEL)
- {
- /* Unset flags. */
- for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
-
- UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
- }
- else
- {
- if (IS_ZEBRA_DEBUG_KERNEL)
- {
- if (gate)
- zlog_info ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
- inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
- p->prefixlen,
- inet_ntop (AF_INET, gate, buf2, BUFSIZ),
- ifindex,
- type);
- else
- zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib",
- inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
- p->prefixlen,
- ifindex,
- type);
- }
- route_unlock_node (rn);
- return ZEBRA_ERR_RTNOEXIST;
- }
- }
-
- if (same)
- rib_delnode (rn, same);
-
- /* Process changes. */
- rib_process (rn, same);
-
- if (same)
- {
- newrib_free (same);
- route_unlock_node (rn);
- }
-
- route_unlock_node (rn);
-
- return 0;
-}
-
-/* Delete all added route and close rib. */
-void
-rib_close_ipv4 ()
-{
- struct route_node *rn;
- struct rib *rib;
-
- for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
- if (! RIB_SYSTEM_ROUTE (rib)
- && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
- rib_uninstall_kernel (rn, rib);
-}
-
-/* Install static route into rib. */
-void
-static_ipv4_install (struct prefix_ipv4 *p, struct static_ipv4 *si)
-{
- struct rib *rib;
- struct route_node *rn;
-
- /* Lookup existing route */
- rn = route_node_get (rib_table_ipv4, (struct prefix *) p);
- for (rib = rn->info; rib; rib = rib->next)
- if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
- break;
-
- if (rib)
- {
- /* Same distance static route is there. Update it with new
- nexthop. */
- rib_uninstall (rn, rib);
- route_unlock_node (rn);
-
- switch (si->type)
- {
- case STATIC_IPV4_GATEWAY:
- nexthop_ipv4_add (rib, &si->gate.ipv4);
- break;
- case STATIC_IPV4_IFNAME:
- nexthop_ifname_add (rib, si->gate.ifname);
- break;
- }
- rib_process (rn, NULL);
- }
- else
- {
- /* This is new static route. */
- rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
- memset (rib, 0, sizeof (struct rib));
-
- rib->type = ZEBRA_ROUTE_STATIC;
- rib->distance = si->distance;
- rib->metric = 0;
- rib->nexthop_num = 0;
-
- switch (si->type)
- {
- case STATIC_IPV4_GATEWAY:
- nexthop_ipv4_add (rib, &si->gate.ipv4);
- break;
- case STATIC_IPV4_IFNAME:
- nexthop_ifname_add (rib, si->gate.ifname);
- break;
- }
-
- /* Link this rib to the tree. */
- rib_addnode (rn, rib);
-
- /* Process this prefix. */
- rib_process (rn, NULL);
- }
-}
-
-int
-static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
-{
- if (nexthop->type == NEXTHOP_TYPE_IPV4
- && si->type == STATIC_IPV4_GATEWAY
- && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
- return 1;
- if (nexthop->type == NEXTHOP_TYPE_IFNAME
- && si->type == STATIC_IPV4_IFNAME
- && strcmp (nexthop->ifname, si->gate.ifname) == 0)
- return 1;
- return 0;;
-}
-
-/* Uninstall static route from RIB. */
-void
-static_ipv4_uninstall (struct prefix_ipv4 *p, struct static_ipv4 *si)
-{
- struct route_node *rn;
- struct rib *rib;
- struct nexthop *nexthop;
-
- /* Lookup existing route with type and distance. */
- rn = route_node_lookup (rib_table_ipv4, (struct prefix *) p);
- if (! rn)
- return;
-
- for (rib = rn->info; rib; rib = rib->next)
- if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
- break;
- if (! rib)
- {
- route_unlock_node (rn);
- return;
- }
-
- /* Lookup nexthop. */
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- if (static_ipv4_nexthop_same (nexthop, si))
- break;
-
- /* Can't find nexthop. */
- if (! nexthop)
- {
- route_unlock_node (rn);
- return;
- }
-
- /* Check nexthop. */
- if (rib->nexthop_num == 1)
- {
- rib_delnode (rn, rib);
- rib_process (rn, rib);
- newrib_free (rib);
- route_unlock_node (rn);
- }
- else
- {
- rib_uninstall (rn, rib);
- nexthop_delete (rib, nexthop);
- nexthop_free (nexthop);
- rib_process (rn, rib);
- }
-
- /* Unlock node. */
- route_unlock_node (rn);
-}
-
-/* Add static route into static route configuration. */
-int
-static_ipv4_add (struct prefix_ipv4 *p, struct in_addr *gate, char *ifname,
- u_char distance, int table)
-{
- u_char type = 0;
- struct route_node *rn;
- struct static_ipv4 *si;
- struct static_ipv4 *pp;
- struct static_ipv4 *cp;
-
- /* Lookup static route prefix. */
- rn = route_node_get (static_table_ipv4, (struct prefix *) p);
-
- /* Make flags. */
- if (gate)
- type = STATIC_IPV4_GATEWAY;
- if (ifname)
- type = STATIC_IPV4_IFNAME;
-
- /* Do nothing if there is a same static route. */
- for (si = rn->info; si; si = si->next)
- {
- if (distance == si->distance
- && type == si->type
- && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
- && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
- {
- route_unlock_node (rn);
- return 0;
- }
- }
-
- /* Make new static route structure. */
- si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
- memset (si, 0, sizeof (struct static_ipv4));
-
- si->type = type;
- si->distance = distance;
-
- if (gate)
- si->gate.ipv4 = *gate;
- if (ifname)
- si->gate.ifname = XSTRDUP (0, ifname);
-
- /* Add new static route information to the tree with sort by
- distance value and gateway address. */
- for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
- {
- if (si->distance < cp->distance)
- break;
- if (si->distance > cp->distance)
- continue;
- if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
- {
- if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
- break;
- if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
- continue;
- }
- }
-
- /* Make linked list. */
- if (pp)
- pp->next = si;
- else
- rn->info = si;
- if (cp)
- cp->prev = si;
- si->prev = pp;
- si->next = cp;
-
- /* Install into rib. */
- static_ipv4_install (p, si);
-
- return 1;
-}
-
-/* Delete static route from static route configuration. */
-int
-static_ipv4_delete (struct prefix_ipv4 *p, struct in_addr *gate, char *ifname,
- u_char distance, int table)
-{
- u_char type = 0;
- struct route_node *rn;
- struct static_ipv4 *si;
-
- /* Lookup static route prefix. */
- rn = route_node_lookup (static_table_ipv4, (struct prefix *) p);
- if (! rn)
- return 0;
-
- /* Make flags. */
- if (gate)
- type = STATIC_IPV4_GATEWAY;
- if (ifname)
- type = STATIC_IPV4_IFNAME;
-
- /* Find same static route is the tree */
- for (si = rn->info; si; si = si->next)
- if (distance == si->distance
- && type == si->type
- && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
- && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
- break;
-
- /* Can't find static route. */
- if (! si)
- {
- route_unlock_node (rn);
- return 0;
- }
-
- /* Install into rib. */
- static_ipv4_uninstall (p, si);
-
- /* Unlink static route from linked list. */
- if (si->prev)
- si->prev->next = si->next;
- else
- rn->info = si->next;
- if (si->next)
- si->next->prev = si->prev;
-
- /* Free static route configuration. */
- XFREE (MTYPE_STATIC_IPV4, si);
-
- return 1;
-}
-
-/* Write IPv4 static route configuration. */
-int
-static_ipv4_write (struct vty *vty)
-{
- struct route_node *rn;
- struct static_ipv4 *si;
- int write;
-
- write = 0;
-
- for (rn = route_top (static_table_ipv4); rn; rn = route_next (rn))
- for (si = rn->info; si; si = si->next)
- {
- vty_out (vty, "ip route %s/%d", inet_ntoa (rn->p.u.prefix4),
- rn->p.prefixlen);
-
- switch (si->type)
- {
- case STATIC_IPV4_GATEWAY:
- vty_out (vty, " %s", inet_ntoa (si->gate.ipv4));
- break;
- case STATIC_IPV4_IFNAME:
- vty_out (vty, " %s", si->gate.ifname);
- break;
- }
-
- if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
- vty_out (vty, " %d", si->distance);
- vty_out (vty, "%s", VTY_NEWLINE);
-
- write = 1;
- }
- return write;
-}
-
-/* General fucntion for static route. */
-int
-static_ipv4_func (struct vty *vty, int add_cmd,
- char *dest_str, char *mask_str, char *gate_str,
- char *distance_str)
-{
- int ret;
- u_char distance;
- struct prefix_ipv4 p;
- struct in_addr gate;
- struct in_addr mask;
- char *ifname;
- int table = rtm_table_default;
-
- ret = str2prefix_ipv4 (dest_str, &p);
- if (ret <= 0)
- {
- vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- /* Cisco like mask notation. */
- if (mask_str)
- {
- ret = inet_aton (mask_str, &mask);
- if (ret == 0)
- {
- vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- p.prefixlen = ip_masklen (mask);
- }
-
- /* Apply mask for given prefix. */
- apply_mask_ipv4 (&p);
-
- /* Administrative distance. */
- if (distance_str)
- distance = atoi (distance_str);
- else
- distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
-
- /* When gateway is A.B.C.D format, gate is treated as nexthop
- address other case gate is treated as interface name. */
- ret = inet_aton (gate_str, &gate);
- if (ret)
- ifname = NULL;
- else
- ifname = gate_str;
-
- if (add_cmd)
- static_ipv4_add (&p, ifname ? NULL : &gate, ifname, distance, table);
- else
- static_ipv4_delete (&p, ifname ? NULL : &gate, ifname, distance, table);
-
- return CMD_SUCCESS;
-}
-
-/* Static route configuration. */
-DEFUN (ip_route,
- ip_route_cmd,
- "ip route A.B.C.D/M (A.B.C.D|INTERFACE)",
- IP_STR
- "Establish static routes\n"
- "IP destination prefix (e.g. 10.0.0.0/8)\n"
- "IP gateway address\n"
- "IP gateway interface name\n")
-{
- return static_ipv4_func (vty, 1, argv[0], NULL, argv[1], NULL);
-}
-
-DEFUN (ip_route_mask,
- ip_route_mask_cmd,
- "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE)",
- IP_STR
- "Establish static routes\n"
- "IP destination prefix\n"
- "IP destination prefix mask\n"
- "IP gateway address\n"
- "IP gateway interface name\n")
-{
- return static_ipv4_func (vty, 1, argv[0], argv[1], argv[2], NULL);
-}
-
-DEFUN (ip_route_pref,
- ip_route_pref_cmd,
- "ip route A.B.C.D/M (A.B.C.D|INTERFACE) <1-255>",
- IP_STR
- "Establish static routes\n"
- "IP destination prefix (e.g. 10.0.0.0/8)\n"
- "IP gateway address\n"
- "IP gateway interface name\n"
- "Distance value for this route\n")
-{
- return static_ipv4_func (vty, 1, argv[0], NULL, argv[1], argv[2]);
-}
-
-DEFUN (ip_route_mask_pref,
- ip_route_mask_pref_cmd,
- "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) <1-255>",
- IP_STR
- "Establish static routes\n"
- "IP destination prefix\n"
- "IP destination prefix mask\n"
- "IP gateway address\n"
- "IP gateway interface name\n"
- "Distance value for this route\n")
-{
- return static_ipv4_func (vty, 1, argv[0], argv[1], argv[2], argv[3]);
-}
-
-DEFUN (no_ip_route,
- no_ip_route_cmd,
- "no ip route A.B.C.D/M (A.B.C.D|INTERFACE)",
- NO_STR
- IP_STR
- "Establish static routes\n"
- "IP destination prefix (e.g. 10.0.0.0/8)\n"
- "IP gateway address\n"
- "IP gateway interface name\n")
-{
- return static_ipv4_func (vty, 0, argv[0], NULL, argv[1], NULL);
-}
-
-DEFUN (no_ip_route_mask,
- no_ip_route_mask_cmd,
- "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE)",
- NO_STR
- IP_STR
- "Establish static routes\n"
- "IP destination prefix\n"
- "IP destination prefix mask\n"
- "IP gateway address\n"
- "IP gateway interface name\n")
-{
- return static_ipv4_func (vty, 0, argv[0], argv[1], argv[2], NULL);
-}
-
-DEFUN (no_ip_route_pref,
- no_ip_route_pref_cmd,
- "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) <1-255>",
- NO_STR
- IP_STR
- "Establish static routes\n"
- "IP destination prefix (e.g. 10.0.0.0/8)\n"
- "IP gateway address\n"
- "IP gateway interface name\n"
- "Distance value for this route\n")
-{
- return static_ipv4_func (vty, 0, argv[0], NULL, argv[1], argv[2]);
-}
-
-DEFUN (no_ip_route_mask_pref,
- no_ip_route_mask_pref_cmd,
- "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) <1-255>",
- NO_STR
- IP_STR
- "Establish static routes\n"
- "IP destination prefix\n"
- "IP destination prefix mask\n"
- "IP gateway address\n"
- "IP gateway interface name\n"
- "Distance value for this route\n")
-{
- return static_ipv4_func (vty, 0, argv[0], argv[1], argv[2], argv[3]);
-}
-
-/* New RIB. Detailed information for IPv4 route. */
-void
-vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
-{
- struct rib *rib;
- struct nexthop *nexthop;
-
- for (rib = rn->info; rib; rib = rib->next)
- {
- vty_out (vty, "Routing entry for %s/%d%s",
- inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
- VTY_NEWLINE);
- vty_out (vty, " Known via \"%s\"", route_info[rib->type].str);
- vty_out (vty, ", distance %d, metric %d", rib->distance, rib->metric);
- if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
- vty_out (vty, ", best");
- if (rib->refcnt)
- vty_out (vty, ", refcnt %ld", rib->refcnt);
- vty_out (vty, "%s", VTY_NEWLINE);
-
-#define ONE_DAY_SECOND 60*60*24
-#define ONE_WEEK_SECOND 60*60*24*7
- if (rib->type == ZEBRA_ROUTE_RIP
- || rib->type == ZEBRA_ROUTE_OSPF
- || rib->type == ZEBRA_ROUTE_ISIS
- || rib->type == ZEBRA_ROUTE_BGP)
- {
- time_t uptime;
- struct tm *tm;
-
- uptime = time (NULL);
- uptime -= rib->uptime;
- tm = gmtime (&uptime);
-
- vty_out (vty, " Last update ");
-
- if (uptime < ONE_DAY_SECOND)
- vty_out (vty, "%02d:%02d:%02d",
- tm->tm_hour, tm->tm_min, tm->tm_sec);
- else if (uptime < ONE_WEEK_SECOND)
- vty_out (vty, "%dd%02dh%02dm",
- tm->tm_yday, tm->tm_hour, tm->tm_min);
- else
- vty_out (vty, "%02dw%dd%02dh",
- tm->tm_yday/7,
- tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
- vty_out (vty, " ago%s", VTY_NEWLINE);
- }
-
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- {
- vty_out (vty, " %c",
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
-
- switch (nexthop->type)
- {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- vty_out (vty, " %s", inet_ntoa (nexthop->gate.ipv4));
- if (nexthop->ifindex)
- vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex));
- break;
- case NEXTHOP_TYPE_IFINDEX:
- vty_out (vty, " directly connected, %s",
- ifindex2ifname (nexthop->ifindex));
- break;
- case NEXTHOP_TYPE_IFNAME:
- vty_out (vty, " directly connected, %s",
- nexthop->ifname);
- break;
- default:
- break;
- }
- if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- vty_out (vty, " inactive");
-
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- {
- vty_out (vty, " (recursive");
-
- switch (nexthop->rtype)
- {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- vty_out (vty, " via %s)", inet_ntoa (nexthop->rgate.ipv4));
- break;
- case NEXTHOP_TYPE_IFINDEX:
- case NEXTHOP_TYPE_IFNAME:
- vty_out (vty, " is directly connected, %s)",
- ifindex2ifname (nexthop->rifindex));
- break;
- default:
- break;
- }
- }
- vty_out (vty, "%s", VTY_NEWLINE);
- }
- vty_out (vty, "%s", VTY_NEWLINE);
- }
-}
-
-void
-vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
-{
- struct nexthop *nexthop;
- int len = 0;
- char buf[BUFSIZ];
-
- /* Nexthop information. */
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- {
- if (nexthop == rib->nexthop)
- {
- /* Prefix information. */
- len = vty_out (vty, "%c%c%c %s/%d",
- route_info[rib->type].c,
- CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)
- ? '>' : ' ',
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
- ? '*' : ' ',
- inet_ntop (AF_INET, &rn->p.u.prefix, buf, BUFSIZ),
- rn->p.prefixlen);
-
- /* Distance and metric display. */
- if (rib->type != ZEBRA_ROUTE_CONNECT
- && rib->type != ZEBRA_ROUTE_KERNEL)
- len += vty_out (vty, " [%d/%d]", rib->distance,
- rib->metric);
- }
- else
- vty_out (vty, " %c%*c",
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
- ? '*' : ' ',
- len - 3, ' ');
-
- switch (nexthop->type)
- {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4));
- if (nexthop->ifindex)
- vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex));
- break;
- case NEXTHOP_TYPE_IFINDEX:
- vty_out (vty, " is directly connected, %s",
- ifindex2ifname (nexthop->ifindex));
- break;
- case NEXTHOP_TYPE_IFNAME:
- vty_out (vty, " is directly connected, %s",
- nexthop->ifname);
- break;
- default:
- break;
- }
- if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- vty_out (vty, " inactive");
-
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- {
- vty_out (vty, " (recursive");
-
- switch (nexthop->rtype)
- {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- vty_out (vty, " via %s)", inet_ntoa (nexthop->rgate.ipv4));
- break;
- case NEXTHOP_TYPE_IFINDEX:
- case NEXTHOP_TYPE_IFNAME:
- vty_out (vty, " is directly connected, %s)",
- ifindex2ifname (nexthop->rifindex));
- break;
- default:
- break;
- }
- }
-
- if (rib->type == ZEBRA_ROUTE_RIP
- || rib->type == ZEBRA_ROUTE_OSPF
- || rib->type == ZEBRA_ROUTE_ISIS
- || rib->type == ZEBRA_ROUTE_BGP)
- {
- time_t uptime;
- struct tm *tm;
-
- uptime = time (NULL);
- uptime -= rib->uptime;
- tm = gmtime (&uptime);
-
-#define ONE_DAY_SECOND 60*60*24
-#define ONE_WEEK_SECOND 60*60*24*7
-
- if (uptime < ONE_DAY_SECOND)
- vty_out (vty, ", %02d:%02d:%02d",
- tm->tm_hour, tm->tm_min, tm->tm_sec);
- else if (uptime < ONE_WEEK_SECOND)
- vty_out (vty, ", %dd%02dh%02dm",
- tm->tm_yday, tm->tm_hour, tm->tm_min);
- else
- vty_out (vty, ", %02dw%dd%02dh",
- tm->tm_yday/7,
- tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
- }
- vty_out (vty, "%s", VTY_NEWLINE);
- }
-}
-
-#define SHOW_ROUTE_V4_HEADER "Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,%s I - IS-IS, %s B - BGP, > - selected route, * - FIB route%s%s"
-
-DEFUN (show_ip_route,
- show_ip_route_cmd,
- "show ip route",
- SHOW_STR
- IP_STR
- "IP routing table\n")
-{
- struct route_node *rn;
- struct rib *rib;
- int first = 1;
-
- /* Show all IPv4 routes. */
- for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
- {
- if (first)
- {
- vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
- first = 0;
- }
- vty_show_ip_route (vty, rn, rib);
- }
- return CMD_SUCCESS;
-}
-
-DEFUN (show_ip_route_prefix_longer,
- show_ip_route_prefix_longer_cmd,
- "show ip route A.B.C.D/M longer-prefixes",
- SHOW_STR
- IP_STR
- "IP routing table\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
- "Show route matching the specified Network/Mask pair only\n")
-{
- struct route_node *rn;
- struct rib *rib;
- struct prefix p;
- int ret;
- int first = 1;
-
- ret = str2prefix (argv[0], &p);
- if (! ret)
- {
- vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- /* Show matched type IPv4 routes. */
- for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
- if (prefix_match (&p, &rn->p))
- {
- if (first)
- {
- vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
- first = 0;
- }
- vty_show_ip_route (vty, rn, rib);
- }
- return CMD_SUCCESS;
-}
-
-DEFUN (show_ip_route_supernets,
- show_ip_route_supernets_cmd,
- "show ip route supernets-only",
- SHOW_STR
- IP_STR
- "IP routing table\n"
- "Show supernet entries only\n")
-{
- struct route_node *rn;
- struct rib *rib;
- u_int32_t addr;
- int first = 1;
-
-
- /* Show matched type IPv4 routes. */
- for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
- {
- addr = ntohl (rn->p.u.prefix4.s_addr);
-
- if ((IN_CLASSC (addr) && rn->p.prefixlen < 24)
- || (IN_CLASSB (addr) && rn->p.prefixlen < 16)
- || (IN_CLASSA (addr) && rn->p.prefixlen < 8))
- {
- if (first)
- {
- vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE,
- VTY_NEWLINE, VTY_NEWLINE);
- first = 0;
- }
- vty_show_ip_route (vty, rn, rib);
- }
- }
- return CMD_SUCCESS;
-}
-
-
-DEFUN (show_ip_route_protocol,
- show_ip_route_protocol_cmd,
- "show ip route (bgp|connected|kernel|ospf|isis|rip|static)",
- SHOW_STR
- IP_STR
- "IP routing table\n"
- "Border Gateway Protocol (BGP)\n"
- "Connected\n"
- "Kernel\n"
- "Open Shortest Path First (OSPF)\n"
- "ISO IS-IS (ISIS)\n"
- "Routing Information Protocol (RIP)\n"
- "Static routes\n")
-{
- int type;
- struct route_node *rn;
- struct rib *rib;
- int first = 1;
-
- if (strncmp (argv[0], "b", 1) == 0)
- type = ZEBRA_ROUTE_BGP;
- else if (strncmp (argv[0], "c", 1) == 0)
- type = ZEBRA_ROUTE_CONNECT;
- else if (strncmp (argv[0], "k", 1) ==0)
- type = ZEBRA_ROUTE_KERNEL;
- else if (strncmp (argv[0], "o", 1) == 0)
- type = ZEBRA_ROUTE_OSPF;
- else if (strncmp (argv[0], "i", 1) == 0)
- type = ZEBRA_ROUTE_ISIS;
- else if (strncmp (argv[0], "r", 1) == 0)
- type = ZEBRA_ROUTE_RIP;
- else if (strncmp (argv[0], "s", 1) == 0)
- type = ZEBRA_ROUTE_STATIC;
- else
- {
- vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- /* Show matched type IPv4 routes. */
- for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
- if (rib->type == type)
- {
- if (first)
- {
- vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE,
- VTY_NEWLINE, VTY_NEWLINE);
- first = 0;
- }
- vty_show_ip_route (vty, rn, rib);
- }
- return CMD_SUCCESS;
-}
-
-DEFUN (show_ip_route_addr,
- show_ip_route_addr_cmd,
- "show ip route A.B.C.D",
- SHOW_STR
- IP_STR
- "IP routing table\n"
- "Network in the IP routing table to display\n")
-{
- int ret;
- struct prefix_ipv4 p;
- struct route_node *rn;
-
- ret = str2prefix_ipv4 (argv[0], &p);
- if (ret <= 0)
- {
- vty_out (vty, "Malformed IPv4 address%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- rn = route_node_match (rib_table_ipv4, (struct prefix *) &p);
- if (! rn)
- {
- vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- vty_show_ip_route_detail (vty, rn);
-
- route_unlock_node (rn);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (show_ip_route_prefix,
- show_ip_route_prefix_cmd,
- "show ip route A.B.C.D/M",
- SHOW_STR
- IP_STR
- "IP routing table\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
-{
- int ret;
- struct prefix_ipv4 p;
- struct route_node *rn;
-
- ret = str2prefix_ipv4 (argv[0], &p);
- if (ret <= 0)
- {
- vty_out (vty, "Malformed IPv4 address%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- rn = route_node_match (rib_table_ipv4, (struct prefix *) &p);
- if (! rn || rn->p.prefixlen != p.prefixlen)
- {
- vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- vty_show_ip_route_detail (vty, rn);
-
- route_unlock_node (rn);
-
- return CMD_SUCCESS;
-}
-
-#ifdef HAVE_IPV6
-int
-rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
- struct in6_addr *gate, unsigned int ifindex, int table)
-{
- if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix))
- return 1;
- if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
- && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
- {
- kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
- return 1;
- }
- return 0;
-}
-
-int
-rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
- struct in6_addr *gate, unsigned int ifindex, int table)
-{
- struct rib *rib;
- struct rib *same = NULL;
- struct route_node *rn;
- struct nexthop *nexthop;
-
- int distance;
- u_int32_t metric = 0;
-
- /* Make sure mask is applied. */
- apply_mask_ipv6 (p);
-
- /* Set default distance by route type. */
- distance = route_info[type].distance;
-
- if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
- distance = 200;
-
- /* Make new rib. */
- if (!table)
- table = RT_TABLE_MAIN;
-
- /* Filter bogus route. */
- if (rib_bogus_ipv6 (type, p, gate, ifindex, table))
- return 0;
-
- /* Lookup route node.*/
- rn = route_node_get (rib_table_ipv6, (struct prefix *) p);
-
- /* If same type of route are installed, treat it as a implicit
- withdraw. */
- for (rib = rn->info; rib; rib = rib->next)
- {
- if (rib->type == ZEBRA_ROUTE_CONNECT)
- {
- nexthop = rib->nexthop;
-
- if (rib->type == type
- && (! table || rib->table == table)
- && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
- && nexthop->ifindex == ifindex)
- {
- rib->refcnt++;
- return 0;
- }
- }
- else if (rib->type == type
- && (! table || (rib->table == table)))
- {
- same = rib;
- rib_delnode (rn, same);
- route_unlock_node (rn);
- break;
- }
- }
-
- /* Allocate new rib structure. */
- rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
- memset (rib, 0, sizeof (struct rib));
- rib->type = type;
- rib->distance = distance;
- rib->flags = flags;
- rib->metric = metric;
- rib->table = table;
- rib->nexthop_num = 0;
- rib->uptime = time (NULL);
-
- /* Nexthop settings. */
- if (gate)
- {
- if (ifindex)
- nexthop_ipv6_ifindex_add (rib, gate, ifindex);
- else
- nexthop_ipv6_add (rib, gate);
- }
- else
- nexthop_ifindex_add (rib, ifindex);
-
- /* If this route is kernel route, set FIB flag to the route. */
- if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
-
- /* Link new rib to node.*/
- rib_addnode (rn, rib);
-
- /* Process this route node. */
- rib_process (rn, same);
-
- /* Free implicit route.*/
- if (same)
- newrib_free (same);
-
- return 0;
-}
-
-int
-rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
- struct in6_addr *gate, unsigned int ifindex, int table)
-{
- struct route_node *rn;
- struct rib *rib;
- struct rib *fib = NULL;
- struct rib *same = NULL;
- struct nexthop *nexthop;
- char buf1[BUFSIZ];
- char buf2[BUFSIZ];
-
- /* Apply mask. */
- apply_mask_ipv6 (p);
-
- /* Lookup route node. */
- rn = route_node_lookup (rib_table_ipv6, (struct prefix *) p);
- if (! rn)
- {
- if (IS_ZEBRA_DEBUG_KERNEL)
- {
- if (gate)
- zlog_info ("route %s/%d via %s ifindex %d doesn't exist in rib",
- inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
- p->prefixlen,
- inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
- ifindex);
- else
- zlog_info ("route %s/%d ifindex %d doesn't exist in rib",
- inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
- p->prefixlen,
- ifindex);
- }
- return ZEBRA_ERR_RTNOEXIST;
- }
-
- /* Lookup same type route. */
- for (rib = rn->info; rib; rib = rib->next)
- {
- if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
- fib = rib;
-
- if (rib->type == ZEBRA_ROUTE_CONNECT)
- {
- nexthop = rib->nexthop;
-
- if (rib->type == type
- && (! table || rib->table == table)
- && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
- && nexthop->ifindex == ifindex)
- {
- if (rib->refcnt)
- {
- rib->refcnt--;
- route_unlock_node (rn);
- route_unlock_node (rn);
- return 0;
- }
- same = rib;
- break;
- }
- }
- else
- {
- if (rib->type == type
- && (! table || rib->table == table))
- {
- same = rib;
- break;
- }
- }
- }
-
- /* If same type of route can't be found and this message is from
- kernel. */
- if (! same)
- {
- if (fib && type == ZEBRA_ROUTE_KERNEL)
- {
- /* Unset flags. */
- for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
-
- UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
- }
- else
- {
- if (IS_ZEBRA_DEBUG_KERNEL)
- {
- if (gate)
- zlog_info ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
- inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
- p->prefixlen,
- inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
- ifindex,
- type);
- else
- zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib",
- inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
- p->prefixlen,
- ifindex,
- type);
- }
- route_unlock_node (rn);
- return ZEBRA_ERR_RTNOEXIST;
- }
- }
-
- if (same)
- rib_delnode (rn, same);
-
- /* Process changes. */
- rib_process (rn, same);
-
- if (same)
- {
- newrib_free (same);
- route_unlock_node (rn);
- }
-
- route_unlock_node (rn);
-
- return 0;
-}
-
-/* Delete non system routes. */
-void
-rib_close_ipv6 ()
-{
- struct route_node *rn;
- struct rib *rib;
-
- for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
- if (! RIB_SYSTEM_ROUTE (rib)
- && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
- rib_uninstall_kernel (rn, rib);
-}
-
-/* Install static route into rib. */
-void
-static_ipv6_install (struct prefix_ipv6 *p, struct static_ipv6 *si)
-{
- struct rib *rib;
- struct route_node *rn;
-
- /* Lookup existing route */
- rn = route_node_get (rib_table_ipv6, (struct prefix *) p);
- for (rib = rn->info; rib; rib = rib->next)
- if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
- break;
-
- if (rib)
- {
- /* Same distance static route is there. Update it with new
- nexthop. */
- rib_uninstall (rn, rib);
- route_unlock_node (rn);
-
- switch (si->type)
- {
- case STATIC_IPV6_GATEWAY:
- nexthop_ipv6_add (rib, &si->ipv6);
- break;
- case STATIC_IPV6_IFNAME:
- nexthop_ifname_add (rib, si->ifname);
- break;
- case STATIC_IPV6_GATEWAY_IFNAME:
- nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
- break;
- }
- rib_process (rn, NULL);
- }
- else
- {
- /* This is new static route. */
- rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
- memset (rib, 0, sizeof (struct rib));
-
- rib->type = ZEBRA_ROUTE_STATIC;
- rib->distance = si->distance;
- rib->metric = 0;
- rib->nexthop_num = 0;
-
- switch (si->type)
- {
- case STATIC_IPV6_GATEWAY:
- nexthop_ipv6_add (rib, &si->ipv6);
- break;
- case STATIC_IPV6_IFNAME:
- nexthop_ifname_add (rib, si->ifname);
- break;
- case STATIC_IPV6_GATEWAY_IFNAME:
- nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
- break;
- }
-
- /* Link this rib to the tree. */
- rib_addnode (rn, rib);
-
- /* Process this prefix. */
- rib_process (rn, NULL);
- }
-}
-
-int
-static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
-{
- if (nexthop->type == NEXTHOP_TYPE_IPV6
- && si->type == STATIC_IPV6_GATEWAY
- && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
- return 1;
- if (nexthop->type == NEXTHOP_TYPE_IFNAME
- && si->type == STATIC_IPV6_IFNAME
- && strcmp (nexthop->ifname, si->ifname) == 0)
- return 1;
- if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
- && si->type == STATIC_IPV6_GATEWAY_IFNAME
- && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
- && strcmp (nexthop->ifname, si->ifname) == 0)
- return 1;
- return 0;;
-}
-
-void
-static_ipv6_uninstall (struct prefix_ipv6 *p, struct static_ipv6 *si)
-{
- struct route_node *rn;
- struct rib *rib;
- struct nexthop *nexthop;
-
- /* Lookup existing route with type and distance. */
- rn = route_node_lookup (rib_table_ipv6, (struct prefix *) p);
- if (! rn)
- return;
-
- for (rib = rn->info; rib; rib = rib->next)
- if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
- break;
- if (! rib)
- {
- route_unlock_node (rn);
- return;
- }
-
- /* Lookup nexthop. */
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- if (static_ipv6_nexthop_same (nexthop, si))
- break;
-
- /* Can't find nexthop. */
- if (! nexthop)
- {
- route_unlock_node (rn);
- return;
- }
-
- /* Check nexthop. */
- if (rib->nexthop_num == 1)
- {
- rib_delnode (rn, rib);
- rib_process (rn, rib);
- newrib_free (rib);
- route_unlock_node (rn);
- }
- else
- {
- rib_uninstall (rn, rib);
- nexthop_delete (rib, nexthop);
- nexthop_free (nexthop);
- rib_process (rn, rib);
- }
-
- /* Unlock node. */
- route_unlock_node (rn);
-}
-
-/* Add static route into static route configuration. */
-int
-static_ipv6_add (struct prefix_ipv6 *p, u_char type, struct in6_addr *gate,
- char *ifname, u_char distance, int table)
-{
- struct route_node *rn;
- struct static_ipv6 *si;
- struct static_ipv6 *pp;
- struct static_ipv6 *cp;
-
- /* Lookup static route prefix. */
- rn = route_node_get (static_table_ipv6, (struct prefix *) p);
-
- /* Do nothing if there is a same static route. */
- for (si = rn->info; si; si = si->next)
- {
- if (distance == si->distance
- && type == si->type
- && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
- && (! ifname || strcmp (ifname, si->ifname) == 0))
- {
- route_unlock_node (rn);
- return 0;
- }
- }
-
- /* Make new static route structure. */
- si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
- memset (si, 0, sizeof (struct static_ipv6));
-
- si->type = type;
- si->distance = distance;
-
- switch (type)
- {
- case STATIC_IPV6_GATEWAY:
- si->ipv6 = *gate;
- break;
- case STATIC_IPV6_IFNAME:
- si->ifname = XSTRDUP (0, ifname);
- break;
- case STATIC_IPV6_GATEWAY_IFNAME:
- si->ipv6 = *gate;
- si->ifname = XSTRDUP (0, ifname);
- break;
- }
-
- /* Add new static route information to the tree with sort by
- distance value and gateway address. */
- for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
- {
- if (si->distance < cp->distance)
- break;
- if (si->distance > cp->distance)
- continue;
- }
-
- /* Make linked list. */
- if (pp)
- pp->next = si;
- else
- rn->info = si;
- if (cp)
- cp->prev = si;
- si->prev = pp;
- si->next = cp;
-
- /* Install into rib. */
- static_ipv6_install (p, si);
-
- return 1;
-}
-
-/* Delete static route from static route configuration. */
-int
-static_ipv6_delete (struct prefix_ipv6 *p, u_char type, struct in6_addr *gate,
- char *ifname, u_char distance, int table)
-{
- struct route_node *rn;
- struct static_ipv6 *si;
-
- /* Lookup static route prefix. */
- rn = route_node_lookup (static_table_ipv6, (struct prefix *) p);
- if (! rn)
- return 0;
-
- /* Find same static route is the tree */
- for (si = rn->info; si; si = si->next)
- if (distance == si->distance
- && type == si->type
- && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
- && (! ifname || strcmp (ifname, si->ifname) == 0))
- break;
-
- /* Can't find static route. */
- if (! si)
- {
- route_unlock_node (rn);
- return 0;
- }
-
- /* Install into rib. */
- static_ipv6_uninstall (p, si);
-
- /* Unlink static route from linked list. */
- if (si->prev)
- si->prev->next = si->next;
- else
- rn->info = si->next;
- if (si->next)
- si->next->prev = si->prev;
-
- /* Free static route configuration. */
- XFREE (MTYPE_STATIC_IPV6, si);
-
- return 1;
-}
-
-/* General fucntion for IPv6 static route. */
-int
-static_ipv6_func (struct vty *vty, int add_cmd, char *dest_str,
- char *gate_str, char *ifname, char *distance_str)
-{
- int ret;
- u_char distance;
- struct prefix_ipv6 p;
- struct in6_addr *gate = NULL;
- struct in6_addr gate_addr;
- u_char type = 0;
- int table = rtm_table_default;
-
- ret = str2prefix_ipv6 (dest_str, &p);
- if (ret <= 0)
- {
- vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- /* Apply mask for given prefix. */
- apply_mask_ipv6 (&p);
-
- /* Administrative distance. */
- if (distance_str)
- distance = atoi (distance_str);
- else
- distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
-
- /* When gateway is valid IPv6 addrees, then gate is treated as
- nexthop address other case gate is treated as interface name. */
- ret = inet_pton (AF_INET6, gate_str, &gate_addr);
-
- if (ifname)
- {
- /* When ifname is specified. It must be come with gateway
- address. */
- if (ret != 1)
- {
- vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- type = STATIC_IPV6_GATEWAY_IFNAME;
- gate = &gate_addr;
- }
- else
- {
- if (ret == 1)
- {
- type = STATIC_IPV6_GATEWAY;
- gate = &gate_addr;
- }
- else
- {
- type = STATIC_IPV6_IFNAME;
- ifname = gate_str;
- }
- }
-
- if (add_cmd)
- static_ipv6_add (&p, type, gate, ifname, distance, table);
- else
- static_ipv6_delete (&p, type, gate, ifname, distance, table);
-
- return CMD_SUCCESS;
-}
-
-/* Write IPv6 static route configuration. */
-int
-static_ipv6_write (struct vty *vty)
-{
- struct route_node *rn;
- struct static_ipv6 *si;
- int write;
- char buf[BUFSIZ];
-
- write = 0;
-
- for (rn = route_top (static_table_ipv6); rn; rn = route_next (rn))
- for (si = rn->info; si; si = si->next)
- {
- vty_out (vty, "ipv6 route %s/%d",
- inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
- rn->p.prefixlen);
-
- switch (si->type)
- {
- case STATIC_IPV6_GATEWAY:
- vty_out (vty, " %s", inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ));
- break;
- case STATIC_IPV6_IFNAME:
- vty_out (vty, " %s", si->ifname);
- break;
- case STATIC_IPV6_GATEWAY_IFNAME:
- vty_out (vty, " %s %s",
- inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ), si->ifname);
- break;
- }
-
- if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
- vty_out (vty, " %d", si->distance);
- vty_out (vty, "%s", VTY_NEWLINE);
-
- write = 1;
- }
- return write;
-}
-
-DEFUN (ipv6_route,
- ipv6_route_cmd,
- "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)",
- IP_STR
- "Establish static routes\n"
- "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
- "IPv6 gateway address\n"
- "IPv6 gateway interface name\n")
-{
- return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL);
-}
-
-DEFUN (ipv6_route_ifname,
- ipv6_route_ifname_cmd,
- "ipv6 route X:X::X:X/M X:X::X:X INTERFACE",
- IP_STR
- "Establish static routes\n"
- "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
- "IPv6 gateway address\n"
- "IPv6 gateway interface name\n")
-{
- return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL);
-}
-
-DEFUN (ipv6_route_pref,
- ipv6_route_pref_cmd,
- "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>",
- IP_STR
- "Establish static routes\n"
- "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
- "IPv6 gateway address\n"
- "IPv6 gateway interface name\n"
- "Distance value for this prefix\n")
-{
- return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2]);
-}
-
-DEFUN (ipv6_route_ifname_pref,
- ipv6_route_ifname_pref_cmd,
- "ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>",
- IP_STR
- "Establish static routes\n"
- "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
- "IPv6 gateway address\n"
- "IPv6 gateway interface name\n"
- "Distance value for this prefix\n")
-{
- return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3]);
-}
-
-DEFUN (no_ipv6_route,
- no_ipv6_route_cmd,
- "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)",
- NO_STR
- IP_STR
- "Establish static routes\n"
- "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
- "IPv6 gateway address\n"
- "IPv6 gateway interface name\n")
-{
- return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL);
-}
-
-DEFUN (no_ipv6_route_ifname,
- no_ipv6_route_ifname_cmd,
- "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE",
- NO_STR
- IP_STR
- "Establish static routes\n"
- "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
- "IPv6 gateway address\n"
- "IPv6 gateway interface name\n")
-{
- return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL);
-}
-
-DEFUN (no_ipv6_route_pref,
- no_ipv6_route_pref_cmd,
- "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>",
- NO_STR
- IP_STR
- "Establish static routes\n"
- "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
- "IPv6 gateway address\n"
- "IPv6 gateway interface name\n"
- "Distance value for this prefix\n")
-{
- return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2]);
-}
-
-DEFUN (no_ipv6_route_ifname_pref,
- no_ipv6_route_ifname_pref_cmd,
- "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>",
- NO_STR
- IP_STR
- "Establish static routes\n"
- "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
- "IPv6 gateway address\n"
- "IPv6 gateway interface name\n"
- "Distance value for this prefix\n")
-{
- return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3]);
-}
-
-/* New RIB. Detailed information for IPv4 route. */
-void
-vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn)
-{
- struct rib *rib;
- struct nexthop *nexthop;
- char buf[BUFSIZ];
-
- for (rib = rn->info; rib; rib = rib->next)
- {
- vty_out (vty, "Routing entry for %s/%d%s",
- inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
- rn->p.prefixlen,
- VTY_NEWLINE);
- vty_out (vty, " Known via \"%s\"", route_info[rib->type].str);
- vty_out (vty, ", distance %d, metric %d", rib->distance, rib->metric);
- if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
- vty_out (vty, ", best");
- if (rib->refcnt)
- vty_out (vty, ", refcnt %ld", rib->refcnt);
- vty_out (vty, "%s", VTY_NEWLINE);
-
-#define ONE_DAY_SECOND 60*60*24
-#define ONE_WEEK_SECOND 60*60*24*7
- if (rib->type == ZEBRA_ROUTE_RIPNG
- || rib->type == ZEBRA_ROUTE_OSPF6
- || rib->type == ZEBRA_ROUTE_ISIS
- || rib->type == ZEBRA_ROUTE_BGP)
- {
- time_t uptime;
- struct tm *tm;
-
- uptime = time (NULL);
- uptime -= rib->uptime;
- tm = gmtime (&uptime);
-
- vty_out (vty, " Last update ");
-
- if (uptime < ONE_DAY_SECOND)
- vty_out (vty, "%02d:%02d:%02d",
- tm->tm_hour, tm->tm_min, tm->tm_sec);
- else if (uptime < ONE_WEEK_SECOND)
- vty_out (vty, "%dd%02dh%02dm",
- tm->tm_yday, tm->tm_hour, tm->tm_min);
- else
- vty_out (vty, "%02dw%dd%02dh",
- tm->tm_yday/7,
- tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
- vty_out (vty, " ago%s", VTY_NEWLINE);
- }
-
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- {
- vty_out (vty, " %c",
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
-
- switch (nexthop->type)
- {
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- case NEXTHOP_TYPE_IPV6_IFNAME:
- vty_out (vty, " %s",
- inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
- if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
- vty_out (vty, ", %s", nexthop->ifname);
- else if (nexthop->ifindex)
- vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex));
- break;
- case NEXTHOP_TYPE_IFINDEX:
- vty_out (vty, " directly connected, %s",
- ifindex2ifname (nexthop->ifindex));
- break;
- case NEXTHOP_TYPE_IFNAME:
- vty_out (vty, " directly connected, %s",
- nexthop->ifname);
- break;
- default:
- break;
- }
- if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- vty_out (vty, " inactive");
-
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- {
- vty_out (vty, " (recursive");
-
- switch (nexthop->rtype)
- {
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- case NEXTHOP_TYPE_IPV6_IFNAME:
- vty_out (vty, " via %s)",
- inet_ntop (AF_INET6, &nexthop->rgate.ipv6,
- buf, BUFSIZ));
- if (nexthop->rifindex)
- vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
- break;
- case NEXTHOP_TYPE_IFINDEX:
- case NEXTHOP_TYPE_IFNAME:
- vty_out (vty, " is directly connected, %s)",
- ifindex2ifname (nexthop->rifindex));
- break;
- default:
- break;
- }
- }
- vty_out (vty, "%s", VTY_NEWLINE);
- }
- vty_out (vty, "%s", VTY_NEWLINE);
- }
-}
-
-void
-vty_show_ipv6_route (struct vty *vty, struct route_node *rn,
- struct rib *rib)
-{
- struct nexthop *nexthop;
- int len = 0;
- char buf[BUFSIZ];
-
- /* Nexthop information. */
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- {
- if (nexthop == rib->nexthop)
- {
- /* Prefix information. */
- len = vty_out (vty, "%c%c%c %s/%d",
- route_info[rib->type].c,
- CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)
- ? '>' : ' ',
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
- ? '*' : ' ',
- inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
- rn->p.prefixlen);
-
- /* Distance and metric display. */
- if (rib->type != ZEBRA_ROUTE_CONNECT
- && rib->type != ZEBRA_ROUTE_KERNEL)
- len += vty_out (vty, " [%d/%d]", rib->distance,
- rib->metric);
- }
- else
- vty_out (vty, " %c%*c",
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
- ? '*' : ' ',
- len - 3, ' ');
-
- switch (nexthop->type)
- {
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- case NEXTHOP_TYPE_IPV6_IFNAME:
- vty_out (vty, " via %s",
- inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
- if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
- vty_out (vty, ", %s", nexthop->ifname);
- else if (nexthop->ifindex)
- vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex));
- break;
- case NEXTHOP_TYPE_IFINDEX:
- vty_out (vty, " is directly connected, %s",
- ifindex2ifname (nexthop->ifindex));
- break;
- case NEXTHOP_TYPE_IFNAME:
- vty_out (vty, " is directly connected, %s",
- nexthop->ifname);
- break;
- default:
- break;
- }
- if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- vty_out (vty, " inactive");
-
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- {
- vty_out (vty, " (recursive");
-
- switch (nexthop->rtype)
- {
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- case NEXTHOP_TYPE_IPV6_IFNAME:
- vty_out (vty, " via %s)",
- inet_ntop (AF_INET6, &nexthop->rgate.ipv6,
- buf, BUFSIZ));
- if (nexthop->rifindex)
- vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
- break;
- case NEXTHOP_TYPE_IFINDEX:
- case NEXTHOP_TYPE_IFNAME:
- vty_out (vty, " is directly connected, %s)",
- ifindex2ifname (nexthop->rifindex));
- break;
- default:
- break;
- }
- }
-
- if (rib->type == ZEBRA_ROUTE_RIPNG
- || rib->type == ZEBRA_ROUTE_OSPF6
- || rib->type == ZEBRA_ROUTE_ISIS
- || rib->type == ZEBRA_ROUTE_BGP)
- {
- time_t uptime;
- struct tm *tm;
-
- uptime = time (NULL);
- uptime -= rib->uptime;
- tm = gmtime (&uptime);
-
-#define ONE_DAY_SECOND 60*60*24
-#define ONE_WEEK_SECOND 60*60*24*7
-
- if (uptime < ONE_DAY_SECOND)
- vty_out (vty, ", %02d:%02d:%02d",
- tm->tm_hour, tm->tm_min, tm->tm_sec);
- else if (uptime < ONE_WEEK_SECOND)
- vty_out (vty, ", %dd%02dh%02dm",
- tm->tm_yday, tm->tm_hour, tm->tm_min);
- else
- vty_out (vty, ", %02dw%dd%02dh",
- tm->tm_yday/7,
- tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
- }
- vty_out (vty, "%s", VTY_NEWLINE);
- }
-}
-
-#define SHOW_ROUTE_V6_HEADER "Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS,%s B - BGP, * - FIB route.%s%s"
-
-DEFUN (show_ipv6_route,
- show_ipv6_route_cmd,
- "show ipv6 route",
- SHOW_STR
- IP_STR
- "IPv6 routing table\n")
-{
- struct route_node *rn;
- struct rib *rib;
- int first = 1;
-
- /* Show all IPv6 route. */
- for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
- {
- if (first)
- {
- vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
- first = 0;
- }
- vty_show_ipv6_route (vty, rn, rib);
- }
- return CMD_SUCCESS;
-}
-
-DEFUN (show_ipv6_route_prefix_longer,
- show_ipv6_route_prefix_longer_cmd,
- "show ipv6 route X:X::X:X/M longer-prefixes",
- SHOW_STR
- IP_STR
- "IPv6 routing table\n"
- "IPv6 prefix\n"
- "Show route matching the specified Network/Mask pair only\n")
-{
- struct route_node *rn;
- struct rib *rib;
- struct prefix p;
- int ret;
- int first = 1;
-
- ret = str2prefix (argv[0], &p);
- if (! ret)
- {
- vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- /* Show matched type IPv6 routes. */
- for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
- if (prefix_match (&p, &rn->p))
- {
- if (first)
- {
- vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
- first = 0;
- }
- vty_show_ipv6_route (vty, rn, rib);
- }
- return CMD_SUCCESS;
-}
-
-DEFUN (show_ipv6_route_protocol,
- show_ipv6_route_protocol_cmd,
- "show ipv6 route (bgp|connected|kernel|ospf6|isis|ripng|static)",
- SHOW_STR
- IP_STR
- "IP routing table\n"
- "Border Gateway Protocol (BGP)\n"
- "Connected\n"
- "Kernel\n"
- "Open Shortest Path First (OSPFv3)\n"
- "ISO IS-IS (ISIS)\n"
- "Routing Information Protocol (RIPng)\n"
- "Static routes\n")
-{
- int type;
- struct route_node *rn;
- struct rib *rib;
- int first = 1;
-
- if (strncmp (argv[0], "b", 1) == 0)
- type = ZEBRA_ROUTE_BGP;
- else if (strncmp (argv[0], "c", 1) == 0)
- type = ZEBRA_ROUTE_CONNECT;
- else if (strncmp (argv[0], "k", 1) ==0)
- type = ZEBRA_ROUTE_KERNEL;
- else if (strncmp (argv[0], "o", 1) == 0)
- type = ZEBRA_ROUTE_OSPF6;
- else if (strncmp (argv[0], "i", 1) == 0)
- type = ZEBRA_ROUTE_ISIS;
- else if (strncmp (argv[0], "r", 1) == 0)
- type = ZEBRA_ROUTE_RIPNG;
- else if (strncmp (argv[0], "s", 1) == 0)
- type = ZEBRA_ROUTE_STATIC;
- else
- {
- vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- /* Show matched type IPv6 routes. */
- for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
- if (rib->type == type)
- {
- if (first)
- {
- vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
- first = 0;
- }
- vty_show_ipv6_route (vty, rn, rib);
- }
- return CMD_SUCCESS;
-}
-
-
-DEFUN (show_ipv6_route_addr,
- show_ipv6_route_addr_cmd,
- "show ipv6 route X:X::X:X",
- SHOW_STR
- IP_STR
- "IPv6 routing table\n"
- "IPv6 Address\n")
-{
- int ret;
- struct prefix_ipv6 p;
- struct route_node *rn;
-
- ret = str2prefix_ipv6 (argv[0], &p);
- if (ret <= 0)
- {
- vty_out (vty, "Malformed IPv6 address%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- rn = route_node_match (rib_table_ipv6, (struct prefix *) &p);
- if (! rn)
- {
- vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- vty_show_ipv6_route_detail (vty, rn);
-
- route_unlock_node (rn);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (show_ipv6_route_prefix,
- show_ipv6_route_prefix_cmd,
- "show ipv6 route X:X::X:X/M",
- SHOW_STR
- IP_STR
- "IPv6 routing table\n"
- "IPv6 prefix\n")
-{
- int ret;
- struct prefix_ipv6 p;
- struct route_node *rn;
-
- ret = str2prefix_ipv6 (argv[0], &p);
- if (ret <= 0)
- {
- vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- rn = route_node_match (rib_table_ipv6, (struct prefix *) &p);
- if (! rn || rn->p.prefixlen != p.prefixlen)
- {
- vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- vty_show_ipv6_route_detail (vty, rn);
-
- route_unlock_node (rn);
-
- return CMD_SUCCESS;
-}
-#endif /* HAVE_IPV6 */
-
-/* RIB update function. */
-void
-rib_update ()
-{
- struct route_node *rn;
-
- for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
- /* Update reachability. */
- rib_process (rn, NULL);
-
-#ifdef HAVE_IPV6
- for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
- rib_process (rn, NULL);
-#endif /* HAVE_IPV6 */
-}
-
-/* Interface goes up. */
-void
-rib_if_up (struct interface *ifp)
-{
- rib_update ();
-}
-
-/* Interface goes down. */
-void
-rib_if_down (struct interface *ifp)
-{
- rib_update ();
-}
-
-/* Clean up routines. */
-void
-rib_weed_table (struct route_table *rib_table)
-{
- struct route_node *rn;
- struct rib *rib;
- struct rib *next;
-
- for (rn = route_top (rib_table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = next)
- {
- next = rib->next;
-
- if (rib->table != rtm_table_default &&
- rib->table != RT_TABLE_MAIN)
- {
- rib_delnode (rn, rib);
- newrib_free (rib);
- route_unlock_node (rn);
- }
- }
-}
-
-/* Delete all routes from unmanaged tables. */
-void
-rib_weed_tables ()
-{
- rib_weed_table (rib_table_ipv4);
-#ifdef HAVE_IPV6
- rib_weed_table (rib_table_ipv6);
-#endif /* HAVE_IPV6 */
-}
-
-void
-rib_sweep_table (struct route_table *rib_table)
-{
- struct route_node *rn;
- struct rib *rib;
- struct rib *next;
- int ret = 0;
-
- for (rn = route_top (rib_table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = next)
- {
- next = rib->next;
-
- if ((rib->type == ZEBRA_ROUTE_KERNEL) &&
- CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
- {
- ret = rib_uninstall_kernel (rn, rib);
-
- if (! ret)
- {
- rib_delnode (rn, rib);
- newrib_free (rib);
- route_unlock_node (rn);
- }
- }
- }
-}
-
-void
-rib_sweep_route ()
-{
- rib_sweep_table (rib_table_ipv4);
-#ifdef HAVE_IPV6
- rib_sweep_table (rib_table_ipv6);
-#endif /* HAVE_IPV6 */
-}
-
-/* Close rib when zebra terminates. */
-void
-rib_close ()
-{
- rib_close_ipv4 ();
-#ifdef HAVE_IPV6
- rib_close_ipv6 ();
-#endif /* HAVE_IPV6 */
-}
-
-/* Static ip route configuration write function. */
-int
-config_write_ip (struct vty *vty)
-{
- int write = 0;
-
- write += static_ipv4_write (vty);
-#ifdef HAVE_IPV6
- write += static_ipv6_write (vty);
-#endif /* HAVE_IPV6 */
-
- return write;
-}
-
-/* IP node for static routes. */
-struct cmd_node ip_node =
-{
- IP_NODE,
- "", /* This node has no interface. */
- 1
-};
-
-/* Routing information base initialize. */
-void
-rib_init ()
-{
- install_node (&ip_node, config_write_ip);
-
- rib_table_ipv4 = route_table_init ();
- static_table_ipv4 = route_table_init ();
-
- install_element (VIEW_NODE, &show_ip_route_cmd);
- install_element (VIEW_NODE, &show_ip_route_addr_cmd);
- install_element (VIEW_NODE, &show_ip_route_prefix_cmd);
- install_element (VIEW_NODE, &show_ip_route_prefix_longer_cmd);
- install_element (VIEW_NODE, &show_ip_route_protocol_cmd);
- install_element (VIEW_NODE, &show_ip_route_supernets_cmd);
- install_element (ENABLE_NODE, &show_ip_route_cmd);
- install_element (ENABLE_NODE, &show_ip_route_addr_cmd);
- install_element (ENABLE_NODE, &show_ip_route_prefix_cmd);
- install_element (ENABLE_NODE, &show_ip_route_prefix_longer_cmd);
- install_element (ENABLE_NODE, &show_ip_route_protocol_cmd);
- install_element (ENABLE_NODE, &show_ip_route_supernets_cmd);
- install_element (CONFIG_NODE, &ip_route_cmd);
- install_element (CONFIG_NODE, &ip_route_mask_cmd);
- install_element (CONFIG_NODE, &no_ip_route_cmd);
- install_element (CONFIG_NODE, &no_ip_route_mask_cmd);
- install_element (CONFIG_NODE, &ip_route_pref_cmd);
- install_element (CONFIG_NODE, &ip_route_mask_pref_cmd);
- install_element (CONFIG_NODE, &no_ip_route_pref_cmd);
- install_element (CONFIG_NODE, &no_ip_route_mask_pref_cmd);
-
-#ifdef HAVE_IPV6
- rib_table_ipv6 = route_table_init ();
- static_table_ipv6 = route_table_init ();
-
- install_element (CONFIG_NODE, &ipv6_route_cmd);
- install_element (CONFIG_NODE, &ipv6_route_ifname_cmd);
- install_element (CONFIG_NODE, &no_ipv6_route_cmd);
- install_element (CONFIG_NODE, &no_ipv6_route_ifname_cmd);
- install_element (CONFIG_NODE, &ipv6_route_pref_cmd);
- install_element (CONFIG_NODE, &ipv6_route_ifname_pref_cmd);
- install_element (CONFIG_NODE, &no_ipv6_route_pref_cmd);
- install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_cmd);
- install_element (VIEW_NODE, &show_ipv6_route_cmd);
- install_element (VIEW_NODE, &show_ipv6_route_protocol_cmd);
- install_element (VIEW_NODE, &show_ipv6_route_addr_cmd);
- install_element (VIEW_NODE, &show_ipv6_route_prefix_cmd);
- install_element (VIEW_NODE, &show_ipv6_route_prefix_longer_cmd);
- install_element (ENABLE_NODE, &show_ipv6_route_cmd);
- install_element (ENABLE_NODE, &show_ipv6_route_protocol_cmd);
- install_element (ENABLE_NODE, &show_ipv6_route_addr_cmd);
- install_element (ENABLE_NODE, &show_ipv6_route_prefix_cmd);
- install_element (ENABLE_NODE, &show_ipv6_route_prefix_longer_cmd);
-#endif /* HAVE_IPV6 */
-}