diff options
author | hasso <hasso> | 2005-01-01 20:49:21 +0000 |
---|---|---|
committer | hasso <hasso> | 2005-01-01 20:49:21 +0000 |
commit | 39f476f9f63fb084bbd1a4f2eb3a77b7ff1a626a (patch) | |
tree | ebeb4f20194ee85dfd25a34d9b11704824f5c877 /isisd/modified/rib.c | |
parent | 1cbc562b0c9f849639e2d95718ad823f6bc7877f (diff) |
There is no need to keep this directory.
Diffstat (limited to 'isisd/modified/rib.c')
-rw-r--r-- | isisd/modified/rib.c | 3321 |
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 */ -} |