From 718e3744195351130f4ce7dbe0613f4b3e23df93 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 13 Dec 2002 20:15:29 +0000 Subject: Initial revision --- bgpd/bgp_route.c | 9053 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 9053 insertions(+) create mode 100644 bgpd/bgp_route.c (limited to 'bgpd/bgp_route.c') diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c new file mode 100644 index 00000000..87d305cb --- /dev/null +++ b/bgpd/bgp_route.c @@ -0,0 +1,9053 @@ +/* BGP routing information + Copyright (C) 1996, 97, 98, 99 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 + +#include "prefix.h" +#include "linklist.h" +#include "memory.h" +#include "command.h" +#include "stream.h" +#include "filter.h" +#include "str.h" +#include "log.h" +#include "routemap.h" +#include "buffer.h" +#include "sockunion.h" +#include "plist.h" +#include "thread.h" + +#include "bgpd/bgpd.h" +#include "bgpd/bgp_table.h" +#include "bgpd/bgp_route.h" +#include "bgpd/bgp_attr.h" +#include "bgpd/bgp_debug.h" +#include "bgpd/bgp_aspath.h" +#include "bgpd/bgp_regex.h" +#include "bgpd/bgp_community.h" +#include "bgpd/bgp_ecommunity.h" +#include "bgpd/bgp_clist.h" +#include "bgpd/bgp_packet.h" +#include "bgpd/bgp_filter.h" +#include "bgpd/bgp_fsm.h" +#include "bgpd/bgp_mplsvpn.h" +#include "bgpd/bgp_nexthop.h" +#include "bgpd/bgp_damp.h" +#include "bgpd/bgp_advertise.h" +#include "bgpd/bgp_zebra.h" + +/* Extern from bgp_dump.c */ +extern char *bgp_origin_str[]; +extern char *bgp_origin_long_str[]; + +struct bgp_node * +bgp_afi_node_get (struct bgp *bgp, afi_t afi, safi_t safi, struct prefix *p, + struct prefix_rd *prd) +{ + struct bgp_node *rn; + struct bgp_node *prn = NULL; + struct bgp_table *table; + + if (safi == SAFI_MPLS_VPN) + { + prn = bgp_node_get (bgp->rib[afi][safi], (struct prefix *) prd); + + if (prn->info == NULL) + prn->info = bgp_table_init (); + else + bgp_unlock_node (prn); + table = prn->info; + } + else + table = bgp->rib[afi][safi]; + + rn = bgp_node_get (table, p); + + if (safi == SAFI_MPLS_VPN) + rn->prn = prn; + + return rn; +} + +/* Allocate new bgp info structure. */ +struct bgp_info * +bgp_info_new () +{ + struct bgp_info *new; + + new = XMALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info)); + memset (new, 0, sizeof (struct bgp_info)); + + return new; +} + +/* Free bgp route information. */ +void +bgp_info_free (struct bgp_info *binfo) +{ + if (binfo->attr) + bgp_attr_unintern (binfo->attr); + + if (binfo->damp_info) + bgp_damp_info_free (binfo->damp_info, 0); + + XFREE (MTYPE_BGP_ROUTE, binfo); +} + +void +bgp_info_add (struct bgp_node *rn, struct bgp_info *ri) +{ + struct bgp_info *top; + + top = rn->info; + + ri->next = rn->info; + ri->prev = NULL; + if (top) + top->prev = ri; + rn->info = ri; +} + +void +bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri) +{ + if (ri->next) + ri->next->prev = ri->prev; + if (ri->prev) + ri->prev->next = ri->next; + else + rn->info = ri->next; +} + +/* Get MED value. If MED value is missing and "bgp bestpath + missing-as-worst" is specified, treat it as the worst value. */ +u_int32_t +bgp_med_value (struct attr *attr, struct bgp *bgp) +{ + if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) + return attr->med; + else + { + if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST)) + return 4294967295ul; + else + return 0; + } +} + +/* Compare two bgp route entity. br is preferable then return 1. */ +int +bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) +{ + u_int32_t new_pref; + u_int32_t exist_pref; + u_int32_t new_med; + u_int32_t exist_med; + struct in_addr new_id; + struct in_addr exist_id; + int new_cluster; + int exist_cluster; + int internal_as_route = 0; + int confed_as_route = 0; + int ret; + + /* 0. Null check. */ + if (new == NULL) + return 0; + if (exist == NULL) + return 1; + + /* 1. Weight check. */ + if (new->attr->weight > exist->attr->weight) + return 1; + if (new->attr->weight < exist->attr->weight) + return 0; + + /* 2. Local preference check. */ + if (new->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) + new_pref = new->attr->local_pref; + else + new_pref = bgp->default_local_pref; + + if (exist->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) + exist_pref = exist->attr->local_pref; + else + exist_pref = bgp->default_local_pref; + + if (new_pref > exist_pref) + return 1; + if (new_pref < exist_pref) + return 0; + + /* 3. Local route check. */ + if (new->sub_type == BGP_ROUTE_STATIC) + return 1; + if (exist->sub_type == BGP_ROUTE_STATIC) + return 0; + + if (new->sub_type == BGP_ROUTE_REDISTRIBUTE) + return 1; + if (exist->sub_type == BGP_ROUTE_REDISTRIBUTE) + return 0; + + if (new->sub_type == BGP_ROUTE_AGGREGATE) + return 1; + if (exist->sub_type == BGP_ROUTE_AGGREGATE) + return 0; + + /* 4. AS path length check. */ + if (! bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE)) + { + if (new->attr->aspath->count < exist->attr->aspath->count) + return 1; + if (new->attr->aspath->count > exist->attr->aspath->count) + return 0; + } + + /* 5. Origin check. */ + if (new->attr->origin < exist->attr->origin) + return 1; + if (new->attr->origin > exist->attr->origin) + return 0; + + /* 6. MED check. */ + internal_as_route = (new->attr->aspath->length == 0 + && exist->attr->aspath->length == 0); + confed_as_route = (new->attr->aspath->length > 0 + && exist->attr->aspath->length > 0 + && new->attr->aspath->count == 0 + && exist->attr->aspath->count == 0); + + if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED) + || (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED) + && confed_as_route) + || aspath_cmp_left (new->attr->aspath, exist->attr->aspath) + || aspath_cmp_left_confed (new->attr->aspath, exist->attr->aspath) + || internal_as_route) + { + new_med = bgp_med_value (new->attr, bgp); + exist_med = bgp_med_value (exist->attr, bgp); + + if (new_med < exist_med) + return 1; + if (new_med > exist_med) + return 0; + } + + /* 7. Peer type check. */ + if (peer_sort (new->peer) == BGP_PEER_EBGP + && peer_sort (exist->peer) == BGP_PEER_IBGP) + return 1; + if (peer_sort (new->peer) == BGP_PEER_EBGP + && peer_sort (exist->peer) == BGP_PEER_CONFED) + return 1; + if (peer_sort (new->peer) == BGP_PEER_IBGP + && peer_sort (exist->peer) == BGP_PEER_EBGP) + return 0; + if (peer_sort (new->peer) == BGP_PEER_CONFED + && peer_sort (exist->peer) == BGP_PEER_EBGP) + return 0; + + /* 8. IGP metric check. */ + if (new->igpmetric < exist->igpmetric) + return 1; + if (new->igpmetric > exist->igpmetric) + return 0; + + /* 9. Maximum path check. */ + + /* 10. If both paths are external, prefer the path that was received + first (the oldest one). This step minimizes route-flap, since a + newer path won't displace an older one, even if it was the + preferred route based on the additional decision criteria below. */ + if (! bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID) + && peer_sort (new->peer) == BGP_PEER_EBGP + && peer_sort (exist->peer) == BGP_PEER_EBGP) + { + if (CHECK_FLAG (new->flags, BGP_INFO_SELECTED)) + return 1; + if (CHECK_FLAG (exist->flags, BGP_INFO_SELECTED)) + return 0; + } + + /* 11. Rourter-ID comparision. */ + if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) + new_id.s_addr = new->attr->originator_id.s_addr; + else + new_id.s_addr = new->peer->remote_id.s_addr; + if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) + exist_id.s_addr = exist->attr->originator_id.s_addr; + else + exist_id.s_addr = exist->peer->remote_id.s_addr; + + if (ntohl (new_id.s_addr) < ntohl (exist_id.s_addr)) + return 1; + if (ntohl (new_id.s_addr) > ntohl (exist_id.s_addr)) + return 0; + + /* 12. Cluster length comparision. */ + if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) + new_cluster = new->attr->cluster->length; + else + new_cluster = 0; + if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) + exist_cluster = exist->attr->cluster->length; + else + exist_cluster = 0; + + if (new_cluster < exist_cluster) + return 1; + if (new_cluster > exist_cluster) + return 0; + + /* 13. Neighbor address comparision. */ + ret = sockunion_cmp (new->peer->su_remote, exist->peer->su_remote); + + if (ret == 1) + return 0; + if (ret == -1) + return 1; + + return 1; +} + +enum filter_type +bgp_input_filter (struct peer *peer, struct prefix *p, struct attr *attr, + afi_t afi, safi_t safi) +{ + struct bgp_filter *filter; + + filter = &peer->filter[afi][safi]; + + if (DISTRIBUTE_IN_NAME (filter)) + if (access_list_apply (DISTRIBUTE_IN (filter), p) == FILTER_DENY) + return FILTER_DENY; + + if (PREFIX_LIST_IN_NAME (filter)) + if (prefix_list_apply (PREFIX_LIST_IN (filter), p) == PREFIX_DENY) + return FILTER_DENY; + + if (FILTER_LIST_IN_NAME (filter)) + if (as_list_apply (FILTER_LIST_IN (filter), attr->aspath)== AS_FILTER_DENY) + return FILTER_DENY; + + return FILTER_PERMIT; +} + +enum filter_type +bgp_output_filter (struct peer *peer, struct prefix *p, struct attr *attr, + afi_t afi, safi_t safi) +{ + struct bgp_filter *filter; + + filter = &peer->filter[afi][safi]; + + if (DISTRIBUTE_OUT_NAME (filter)) + if (access_list_apply (DISTRIBUTE_OUT (filter), p) == FILTER_DENY) + return FILTER_DENY; + + if (PREFIX_LIST_OUT_NAME (filter)) + if (prefix_list_apply (PREFIX_LIST_OUT (filter), p) == PREFIX_DENY) + return FILTER_DENY; + + if (FILTER_LIST_OUT_NAME (filter)) + if (as_list_apply (FILTER_LIST_OUT (filter), attr->aspath) == AS_FILTER_DENY) + return FILTER_DENY; + + return FILTER_PERMIT; +} + +/* If community attribute includes no_export then return 1. */ +int +bgp_community_filter (struct peer *peer, struct attr *attr) +{ + if (attr->community) + { + /* NO_ADVERTISE check. */ + if (community_include (attr->community, COMMUNITY_NO_ADVERTISE)) + return 1; + + /* NO_EXPORT check. */ + if (peer_sort (peer) == BGP_PEER_EBGP && + community_include (attr->community, COMMUNITY_NO_EXPORT)) + return 1; + + /* NO_EXPORT_SUBCONFED check. */ + if (peer_sort (peer) == BGP_PEER_EBGP + || peer_sort (peer) == BGP_PEER_CONFED) + if (community_include (attr->community, COMMUNITY_NO_EXPORT_SUBCONFED)) + return 1; + } + return 0; +} + +/* Route reflection loop check. */ +static int +bgp_cluster_filter (struct peer *peer, struct attr *attr) +{ + struct in_addr cluster_id; + + if (attr->cluster) + { + if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID) + cluster_id = peer->bgp->cluster_id; + else + cluster_id = peer->bgp->router_id; + + if (cluster_loop_check (attr->cluster, cluster_id)) + return 1; + } + return 0; +} + +int +bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr, + afi_t afi, safi_t safi) +{ + struct bgp_filter *filter; + struct bgp_info info; + route_map_result_t ret; + + filter = &peer->filter[afi][safi]; + + /* Apply default weight value. */ + attr->weight = peer->weight; + + /* Route map apply. */ + if (ROUTE_MAP_IN_NAME (filter)) + { + /* Duplicate current value to new strucutre for modification. */ + info.peer = peer; + info.attr = attr; + + /* Apply BGP route map to the attribute. */ + ret = route_map_apply (ROUTE_MAP_IN (filter), p, RMAP_BGP, &info); + if (ret == RMAP_DENYMATCH) + { + /* Free newly generated AS path and community by route-map. */ + bgp_attr_flush (attr); + return RMAP_DENY; + } + } + return RMAP_PERMIT; +} + +int +bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, + struct attr *attr, afi_t afi, safi_t safi) +{ + int ret; + char buf[SU_ADDRSTRLEN]; + struct bgp_filter *filter; + struct bgp_info info; + struct peer *from; + struct bgp *bgp; + struct attr dummy_attr; + int transparent; + int reflect; + + from = ri->peer; + filter = &peer->filter[afi][safi]; + bgp = peer->bgp; + +#ifdef DISABLE_BGP_ANNOUNCE + return 0; +#endif + + /* Do not send back route to sender. */ + if (from == peer) + return 0; + + /* Aggregate-address suppress check. */ + if (ri->suppress) + if (! UNSUPPRESS_MAP_NAME (filter)) + return 0; + + /* Default route check. */ + if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE)) + { + if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY) + return 0; +#ifdef HAVE_IPV6 + else if (p->family == AF_INET6 && p->prefixlen == 0) + return 0; +#endif /* HAVE_IPV6 */ + } + + /* If community is not disabled check the no-export and local. */ + if (bgp_community_filter (peer, ri->attr)) + return 0; + + /* If the attribute has originator-id and it is same as remote + peer's id. */ + if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)) + { + if (IPV4_ADDR_SAME (&peer->remote_id, &ri->attr->originator_id)) + { + if (BGP_DEBUG (filter, FILTER)) + zlog (peer->log, LOG_INFO, + "%s [Update:SEND] %s/%d originator-id is same as remote router-id", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); + return 0; + } + } + + /* ORF prefix-list filter check */ + if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) + && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) + || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))) + if (peer->orf_plist[afi][safi]) + { + if (prefix_list_apply (peer->orf_plist[afi][safi], p) == PREFIX_DENY) + return 0; + } + + /* Output filter check. */ + if (bgp_output_filter (peer, p, ri->attr, afi, safi) == FILTER_DENY) + { + if (BGP_DEBUG (filter, FILTER)) + zlog (peer->log, LOG_INFO, + "%s [Update:SEND] %s/%d is filtered", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); + return 0; + } + +#ifdef BGP_SEND_ASPATH_CHECK + /* AS path loop check. */ + if (aspath_loop_check (ri->attr->aspath, peer->as)) + { + if (BGP_DEBUG (filter, FILTER)) + zlog (peer->log, LOG_INFO, + "%s [Update:SEND] suppress announcement to peer AS %d is AS path.", + peer->host, peer->as); + return 0; + } +#endif /* BGP_SEND_ASPATH_CHECK */ + + /* If we're a CONFED we need to loop check the CONFED ID too */ + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) + { + if (aspath_loop_check(ri->attr->aspath, bgp->confed_id)) + { + if (BGP_DEBUG (filter, FILTER)) + zlog (peer->log, LOG_INFO, + "%s [Update:SEND] suppress announcement to peer AS %d is AS path.", + peer->host, + bgp->confed_id); + return 0; + } + } + + /* Route-Reflect check. */ + if (peer_sort (from) == BGP_PEER_IBGP && peer_sort (peer) == BGP_PEER_IBGP) + reflect = 1; + else + reflect = 0; + + /* IBGP reflection check. */ + if (reflect) + { + /* A route from a Client peer. */ + if (CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) + { + /* Reflect to all the Non-Client peers and also to the + Client peers other than the originator. Originator check + is already done. So there is noting to do. */ + /* no bgp client-to-client reflection check. */ + if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT)) + if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) + return 0; + } + else + { + /* A route from a Non-client peer. Reflect to all other + clients. */ + if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) + return 0; + } + } + + /* For modify attribute, copy it to temporary structure. */ + *attr = *ri->attr; + + /* If local-preference is not set. */ + if ((peer_sort (peer) == BGP_PEER_IBGP + || peer_sort (peer) == BGP_PEER_CONFED) + && (! (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))) + { + attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); + attr->local_pref = bgp->default_local_pref; + } + + /* Transparency check. */ + if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) + && CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) + transparent = 1; + else + transparent = 0; + + /* Remove MED if its an EBGP peer - will get overwritten by route-maps */ + if (peer_sort (peer) == BGP_PEER_EBGP + && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) + { + if (ri->peer != bgp->peer_self && ! transparent + && ! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) + attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)); + } + + /* next-hop-set */ + if (transparent || reflect + || (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED) + && ((p->family == AF_INET && attr->nexthop.s_addr) + || (p->family == AF_INET6 && ri->peer != bgp->peer_self)))) + { + /* NEXT-HOP Unchanged. */ + } + else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) + || (p->family == AF_INET && attr->nexthop.s_addr == 0) +#ifdef HAVE_IPV6 + || (p->family == AF_INET6 && ri->peer == bgp->peer_self) +#endif /* HAVE_IPV6 */ + || (peer_sort (peer) == BGP_PEER_EBGP + && bgp_multiaccess_check_v4 (attr->nexthop, peer->host) == 0)) + { + /* Set IPv4 nexthop. */ + if (p->family == AF_INET) + { + if (safi == SAFI_MPLS_VPN) + memcpy (&attr->mp_nexthop_global_in, &peer->nexthop.v4, IPV4_MAX_BYTELEN); + else + memcpy (&attr->nexthop, &peer->nexthop.v4, IPV4_MAX_BYTELEN); + } +#ifdef HAVE_IPV6 + /* Set IPv6 nexthop. */ + if (p->family == AF_INET6) + { + /* IPv6 global nexthop must be included. */ + memcpy (&attr->mp_nexthop_global, &peer->nexthop.v6_global, + IPV6_MAX_BYTELEN); + attr->mp_nexthop_len = 16; + } +#endif /* HAVE_IPV6 */ + } + +#ifdef HAVE_IPV6 + if (p->family == AF_INET6) + { + /* Link-local address should not be transit to different peer. */ + attr->mp_nexthop_len = 16; + + /* Set link-local address for shared network peer. */ + if (peer->shared_network + && ! IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local)) + { + memcpy (&attr->mp_nexthop_local, &peer->nexthop.v6_local, + IPV6_MAX_BYTELEN); + attr->mp_nexthop_len = 32; + } + + /* If bgpd act as BGP-4+ route-reflector, do not send link-local + address.*/ + if (reflect) + attr->mp_nexthop_len = 16; + + /* If BGP-4+ link-local nexthop is not link-local nexthop. */ + if (! IN6_IS_ADDR_LINKLOCAL (&peer->nexthop.v6_local)) + attr->mp_nexthop_len = 16; + } +#endif /* HAVE_IPV6 */ + + /* If this is EBGP peer and remove-private-AS is set. */ + if (peer_sort (peer) == BGP_PEER_EBGP + && peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS) + && aspath_private_as_check (attr->aspath)) + attr->aspath = aspath_empty_get (); + + /* Route map & unsuppress-map apply. */ + if (ROUTE_MAP_OUT_NAME (filter) + || ri->suppress) + { + info.peer = peer; + info.attr = attr; + + /* The route reflector is not allowed to modify the attributes + of the reflected IBGP routes. */ + if (peer_sort (from) == BGP_PEER_IBGP + && peer_sort (peer) == BGP_PEER_IBGP) + { + dummy_attr = *attr; + info.attr = &dummy_attr; + } + + if (ri->suppress) + ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info); + else + ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info); + + if (ret == RMAP_DENYMATCH) + { + bgp_attr_flush (attr); + return 0; + } + } + return 1; +} + +int +bgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi) +{ + struct prefix *p; + struct bgp_info *ri; + struct bgp_info *new_select; + struct bgp_info *old_select; + struct listnode *nn; + struct peer *peer; + struct attr attr; + struct bgp_info *ri1; + struct bgp_info *ri2; + + p = &rn->p; + + /* bgp deterministic-med */ + new_select = NULL; + if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) + for (ri1 = rn->info; ri1; ri1 = ri1->next) + { + if (CHECK_FLAG (ri1->flags, BGP_INFO_DMED_CHECK)) + continue; + if (BGP_INFO_HOLDDOWN (ri1)) + continue; + + new_select = ri1; + if (ri1->next) + for (ri2 = ri1->next; ri2; ri2 = ri2->next) + { + if (CHECK_FLAG (ri2->flags, BGP_INFO_DMED_CHECK)) + continue; + if (BGP_INFO_HOLDDOWN (ri2)) + continue; + + if (aspath_cmp_left (ri1->attr->aspath, ri2->attr->aspath) + || aspath_cmp_left_confed (ri1->attr->aspath, + ri2->attr->aspath)) + { + if (bgp_info_cmp (bgp, ri2, new_select)) + { + UNSET_FLAG (new_select->flags, BGP_INFO_DMED_SELECTED); + new_select = ri2; + } + + SET_FLAG (ri2->flags, BGP_INFO_DMED_CHECK); + } + } + SET_FLAG (new_select->flags, BGP_INFO_DMED_CHECK); + SET_FLAG (new_select->flags, BGP_INFO_DMED_SELECTED); + } + + /* Check old selected route and new selected route. */ + old_select = NULL; + new_select = NULL; + for (ri = rn->info; ri; ri = ri->next) + { + if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) + old_select = ri; + + if (BGP_INFO_HOLDDOWN (ri)) + continue; + + if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED) + && (! CHECK_FLAG (ri->flags, BGP_INFO_DMED_SELECTED))) + { + UNSET_FLAG (ri->flags, BGP_INFO_DMED_CHECK); + continue; + } + UNSET_FLAG (ri->flags, BGP_INFO_DMED_CHECK); + UNSET_FLAG (ri->flags, BGP_INFO_DMED_SELECTED); + + if (bgp_info_cmp (bgp, ri, new_select)) + new_select = ri; + } + + /* Nothing to do. */ + if (old_select && old_select == new_select) + { + if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED)) + { + if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED)) + bgp_zebra_announce (p, old_select, bgp); + return 0; + } + } + + if (old_select) + UNSET_FLAG (old_select->flags, BGP_INFO_SELECTED); + if (new_select) + { + SET_FLAG (new_select->flags, BGP_INFO_SELECTED); + UNSET_FLAG (new_select->flags, BGP_INFO_ATTR_CHANGED); + } + + /* Check each BGP peer. */ + LIST_LOOP (bgp->peer, peer, nn) + { + /* Announce route to Established peer. */ + if (peer->status != Established) + continue; + + /* Address family configuration check. */ + if (! peer->afc_nego[afi][safi]) + continue; + + /* First update is deferred until ORF or ROUTE-REFRESH is received */ + if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH)) + continue; + + /* Announcement to peer->conf. If the route is filtered, + withdraw it. */ + if (new_select + && bgp_announce_check (new_select, peer, p, &attr, afi, safi)) + bgp_adj_out_set (rn, peer, p, &attr, afi, safi, new_select); + else + bgp_adj_out_unset (rn, peer, p, afi, safi); + } + + /* FIB update. */ + if (safi == SAFI_UNICAST && ! bgp->name && + ! bgp_option_check (BGP_OPT_NO_FIB)) + { + if (new_select + && new_select->type == ZEBRA_ROUTE_BGP + && new_select->sub_type == BGP_ROUTE_NORMAL) + bgp_zebra_announce (p, new_select, bgp); + else + { + /* Withdraw the route from the kernel. */ + if (old_select + && old_select->type == ZEBRA_ROUTE_BGP + && old_select->sub_type == BGP_ROUTE_NORMAL) + bgp_zebra_withdraw (p, old_select); + } + } + return 0; +} + +int +bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, safi_t safi) +{ + if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX) + && peer->pcount[afi][safi] >= peer->pmax[afi][safi]) + { + zlog (peer->log, LOG_INFO, + "MAXPFXEXCEED: No. of prefix received from %s (afi %d): %ld exceed limit %ld", + peer->host, afi, peer->pcount[afi][safi], peer->pmax[afi][safi]); + if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) + { + char ndata[7]; + + ndata[0] = (u_char)(afi >> 8); + ndata[1] = (u_char) afi; + ndata[3] = (u_char)(peer->pmax[afi][safi] >> 24); + ndata[4] = (u_char)(peer->pmax[afi][safi] >> 16); + ndata[5] = (u_char)(peer->pmax[afi][safi] >> 8); + ndata[6] = (u_char)(peer->pmax[afi][safi]); + + if (safi == SAFI_MPLS_VPN) + safi = BGP_SAFI_VPNV4; + ndata[2] = (u_char) safi; + + bgp_notify_send_with_data (peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_MAX_PREFIX, + ndata, 7); + SET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); + return 1; + } + } + return 0; +} + +void +bgp_rib_remove (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer, + afi_t afi, safi_t safi) +{ + if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) + { + peer->pcount[afi][safi]--; + bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi); + UNSET_FLAG (ri->flags, BGP_INFO_VALID); + bgp_process (peer->bgp, rn, afi, safi); + } + bgp_info_delete (rn, ri); + bgp_info_free (ri); + bgp_unlock_node (rn); +} + +void +bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer, + afi_t afi, safi_t safi, int force) +{ + int valid; + int status = BGP_DAMP_NONE; + + if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) + { + peer->pcount[afi][safi]--; + bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi); + } + + if (! force) + { + if (CHECK_FLAG (peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) + && peer_sort (peer) == BGP_PEER_EBGP) + status = bgp_damp_withdraw (ri, rn, afi, safi, 0); + + if (status == BGP_DAMP_SUPPRESSED) + return; + } + + valid = CHECK_FLAG (ri->flags, BGP_INFO_VALID); + UNSET_FLAG (ri->flags, BGP_INFO_VALID); + bgp_process (peer->bgp, rn, afi, safi); + + if (valid) + SET_FLAG (ri->flags, BGP_INFO_VALID); + + if (status != BGP_DAMP_USED) + { + bgp_info_delete (rn, ri); + bgp_info_free (ri); + bgp_unlock_node (rn); + } +} + +int +bgp_update (struct peer *peer, struct prefix *p, struct attr *attr, + afi_t afi, safi_t safi, int type, int sub_type, + struct prefix_rd *prd, u_char *tag, int soft_reconfig) +{ + int ret; + int aspath_loop_count = 0; + struct bgp_node *rn; + struct bgp *bgp; + struct attr new_attr; + struct attr *attr_new; + struct bgp_info *ri; + struct bgp_info *new; + char *reason; + char buf[SU_ADDRSTRLEN]; + + bgp = peer->bgp; + rn = bgp_afi_node_get (bgp, afi, safi, p, prd); + + /* When peer's soft reconfiguration enabled. Record input packet in + Adj-RIBs-In. */ + if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) + && peer != bgp->peer_self && ! soft_reconfig) + bgp_adj_in_set (rn, peer, attr); + + /* Check previously received route. */ + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type) + break; + + /* AS path local-as loop check. */ + if (peer->change_local_as) + { + if (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) + aspath_loop_count = 1; + + if (aspath_loop_check (attr->aspath, peer->change_local_as) > aspath_loop_count) + { + reason = "as-path contains our own AS;"; + goto filtered; + } + } + + /* AS path loop check. */ + if (aspath_loop_check (attr->aspath, bgp->as) > peer->allowas_in[afi][safi] + || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) + && aspath_loop_check(attr->aspath, bgp->confed_id) + > peer->allowas_in[afi][safi])) + { + reason = "as-path contains our own AS;"; + goto filtered; + } + + /* Route reflector originator ID check. */ + if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID) + && IPV4_ADDR_SAME (&bgp->router_id, &attr->originator_id)) + { + reason = "originator is us;"; + goto filtered; + } + + /* Route reflector cluster ID check. */ + if (bgp_cluster_filter (peer, attr)) + { + reason = "reflected from the same cluster;"; + goto filtered; + } + + /* Apply incoming filter. */ + if (bgp_input_filter (peer, p, attr, afi, safi) == FILTER_DENY) + { + reason = "filter;"; + goto filtered; + } + + /* Apply incoming route-map. */ + new_attr = *attr; + + if (bgp_input_modifier (peer, p, &new_attr, afi, safi) == RMAP_DENY) + { + reason = "route-map;"; + goto filtered; + } + + /* IPv4 unicast next hop check. */ + if (afi == AFI_IP && safi == SAFI_UNICAST) + { + /* If the peer is EBGP and nexthop is not on connected route, + discard it. */ + if (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl == 1 + && ! bgp_nexthop_check_ebgp (afi, &new_attr) + && ! CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP)) + { + reason = "non-connected next-hop;"; + goto filtered; + } + + /* Next hop must not be 0.0.0.0 nor Class E address. Next hop + must not be my own address. */ + if (bgp_nexthop_self (afi, &new_attr) + || new_attr.nexthop.s_addr == 0 + || ntohl (new_attr.nexthop.s_addr) >= 0xe0000000) + { + reason = "martian next-hop;"; + goto filtered; + } + } + + attr_new = bgp_attr_intern (&new_attr); + + /* If the update is implicit withdraw. */ + if (ri) + { + ri->uptime = time (NULL); + + /* Same attribute comes in. */ + if (attrhash_cmp (ri->attr, attr_new)) + { + UNSET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED); + + if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) + && peer_sort (peer) == BGP_PEER_EBGP + && CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) + { + if (BGP_DEBUG (update, UPDATE_IN)) + zlog (peer->log, LOG_INFO, "%s rcvd %s/%d", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); + + peer->pcount[afi][safi]++; + ret = bgp_damp_update (ri, rn, afi, safi); + if (ret != BGP_DAMP_SUPPRESSED) + { + bgp_aggregate_increment (bgp, p, ri, afi, safi); + bgp_process (bgp, rn, afi, safi); + } + } + else + { + if (BGP_DEBUG (update, UPDATE_IN)) + zlog (peer->log, LOG_INFO, + "%s rcvd %s/%d...duplicate ignored", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); + } + + bgp_unlock_node (rn); + bgp_attr_unintern (attr_new); + return 0; + } + + /* Received Logging. */ + if (BGP_DEBUG (update, UPDATE_IN)) + zlog (peer->log, LOG_INFO, "%s rcvd %s/%d", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); + + /* The attribute is changed. */ + SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED); + + /* Update bgp route dampening information. */ + if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) + && peer_sort (peer) == BGP_PEER_EBGP) + { + /* This is implicit withdraw so we should update dampening + information. */ + if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) + bgp_damp_withdraw (ri, rn, afi, safi, 1); + else + peer->pcount[afi][safi]++; + } + + bgp_aggregate_decrement (bgp, p, ri, afi, safi); + + /* Update to new attribute. */ + bgp_attr_unintern (ri->attr); + ri->attr = attr_new; + + /* Update MPLS tag. */ + if (safi == SAFI_MPLS_VPN) + memcpy (ri->tag, tag, 3); + + /* Update bgp route dampening information. */ + if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) + && peer_sort (peer) == BGP_PEER_EBGP) + { + /* Now we do normal update dampening. */ + ret = bgp_damp_update (ri, rn, afi, safi); + if (ret == BGP_DAMP_SUPPRESSED) + { + bgp_unlock_node (rn); + return 0; + } + } + + /* Nexthop reachability check. */ + if ((afi == AFI_IP || afi == AFI_IP6) + && safi == SAFI_UNICAST + && (peer_sort (peer) == BGP_PEER_IBGP + || (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1) + || CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))) + { + if (bgp_nexthop_lookup (afi, peer, ri, NULL, NULL)) + SET_FLAG (ri->flags, BGP_INFO_VALID); + else + UNSET_FLAG (ri->flags, BGP_INFO_VALID); + } + else + SET_FLAG (ri->flags, BGP_INFO_VALID); + + /* Process change. */ + bgp_aggregate_increment (bgp, p, ri, afi, safi); + + bgp_process (bgp, rn, afi, safi); + bgp_unlock_node (rn); + return 0; + } + + /* Received Logging. */ + if (BGP_DEBUG (update, UPDATE_IN)) + { + zlog (peer->log, LOG_INFO, "%s rcvd %s/%d", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); + } + + /* Increment prefix counter */ + peer->pcount[afi][safi]++; + + /* Make new BGP info. */ + new = bgp_info_new (); + new->type = type; + new->sub_type = sub_type; + new->peer = peer; + new->attr = attr_new; + new->uptime = time (NULL); + + /* Update MPLS tag. */ + if (safi == SAFI_MPLS_VPN) + memcpy (new->tag, tag, 3); + + /* Nexthop reachability check. */ + if ((afi == AFI_IP || afi == AFI_IP6) + && safi == SAFI_UNICAST + && (peer_sort (peer) == BGP_PEER_IBGP + || (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1) + || CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))) + { + if (bgp_nexthop_lookup (afi, peer, new, NULL, NULL)) + SET_FLAG (new->flags, BGP_INFO_VALID); + else + UNSET_FLAG (new->flags, BGP_INFO_VALID); + } + else + SET_FLAG (new->flags, BGP_INFO_VALID); + + /* Aggregate address increment. */ + bgp_aggregate_increment (bgp, p, new, afi, safi); + + /* Register new BGP information. */ + bgp_info_add (rn, new); + + /* If maximum prefix count is configured and current prefix + count exeed it. */ + if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) + if (bgp_maximum_prefix_overflow (peer, afi, safi)) + return -1; + + /* Process change. */ + bgp_process (bgp, rn, afi, safi); + + return 0; + + /* This BGP update is filtered. Log the reason then update BGP + entry. */ + filtered: + if (BGP_DEBUG (update, UPDATE_IN)) + zlog (peer->log, LOG_INFO, + "%s rcvd UPDATE about %s/%d -- DENIED due to: %s", + peer->host, + inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen, reason); + + if (ri) + bgp_rib_withdraw (rn, ri, peer, afi, safi, 1); + + bgp_unlock_node (rn); + + return 0; +} + +int +bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr, + int afi, int safi, int type, int sub_type, struct prefix_rd *prd, + u_char *tag) +{ + struct bgp *bgp; + char buf[SU_ADDRSTRLEN]; + struct bgp_node *rn; + struct bgp_info *ri; + + bgp = peer->bgp; + + /* Logging. */ + if (BGP_DEBUG (update, UPDATE_IN)) + zlog (peer->log, LOG_INFO, "%s rcvd UPDATE about %s/%d -- withdrawn", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); + + /* Lookup node. */ + rn = bgp_afi_node_get (bgp, afi, safi, p, prd); + + /* If peer is soft reconfiguration enabled. Record input packet for + further calculation. */ + if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) + && peer != bgp->peer_self) + bgp_adj_in_unset (rn, peer); + + /* Lookup withdrawn route. */ + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type) + break; + + /* Withdraw specified route from routing table. */ + if (ri && ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) + bgp_rib_withdraw (rn, ri, peer, afi, safi, 0); + else if (BGP_DEBUG (update, UPDATE_IN)) + zlog (peer->log, LOG_INFO, + "%s Can't find the route %s/%d", peer->host, + inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); + + /* Unlock bgp_node_get() lock. */ + bgp_unlock_node (rn); + + return 0; +} + +void +bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw) +{ + struct bgp *bgp; + struct attr attr; + struct aspath *aspath; + struct prefix p; + struct bgp_info binfo; + struct peer *from; + int ret = RMAP_DENYMATCH; + + bgp = peer->bgp; + from = bgp->peer_self; + + bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); + aspath = attr.aspath; + attr.local_pref = bgp->default_local_pref; + memcpy (&attr.nexthop, &peer->nexthop.v4, IPV4_MAX_BYTELEN); + + if (afi == AFI_IP) + str2prefix ("0.0.0.0/0", &p); +#ifdef HAVE_IPV6 + else if (afi == AFI_IP6) + { + str2prefix ("::/0", &p); + + /* IPv6 global nexthop must be included. */ + memcpy (&attr.mp_nexthop_global, &peer->nexthop.v6_global, + IPV6_MAX_BYTELEN); + attr.mp_nexthop_len = 16; + + /* If the peer is on shared nextwork and we have link-local + nexthop set it. */ + if (peer->shared_network + && !IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local)) + { + memcpy (&attr.mp_nexthop_local, &peer->nexthop.v6_local, + IPV6_MAX_BYTELEN); + attr.mp_nexthop_len = 32; + } + } +#endif /* HAVE_IPV6 */ + else + return; + + if (peer->default_rmap[afi][safi].name) + { + binfo.peer = bgp->peer_self; + binfo.attr = &attr; + + ret = route_map_apply (peer->default_rmap[afi][safi].map, &p, + RMAP_BGP, &binfo); + + if (ret == RMAP_DENYMATCH) + { + bgp_attr_flush (&attr); + withdraw = 1; + } + } + + if (withdraw) + { + if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE)) + bgp_default_withdraw_send (peer, afi, safi); + UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE); + } + else + { + SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE); + bgp_default_update_send (peer, &attr, afi, safi, from); + } + + aspath_unintern (aspath); +} + +static void +bgp_announce_table (struct peer *peer, afi_t afi, safi_t safi, + struct bgp_table *table) +{ + struct bgp_node *rn; + struct bgp_info *ri; + struct attr attr; + + if (! table) + table = peer->bgp->rib[afi][safi]; + + if (safi != SAFI_MPLS_VPN + && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) + bgp_default_originate (peer, afi, safi, 0); + + for (rn = bgp_table_top (table); rn; rn = bgp_route_next(rn)) + for (ri = rn->info; ri; ri = ri->next) + if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) && ri->peer != peer) + { + if (bgp_announce_check (ri, peer, &rn->p, &attr, afi, safi)) + bgp_adj_out_set (rn, peer, &rn->p, &attr, afi, safi, ri); + else + bgp_adj_out_unset (rn, peer, &rn->p, afi, safi); + } +} + +void +bgp_announce_route (struct peer *peer, afi_t afi, safi_t safi) +{ + struct bgp_node *rn; + struct bgp_table *table; + + if (peer->status != Established) + return; + + if (! peer->afc_nego[afi][safi]) + return; + + /* First update is deferred until ORF or ROUTE-REFRESH is received */ + if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH)) + return; + + if (safi != SAFI_MPLS_VPN) + bgp_announce_table (peer, afi, safi, NULL); + else + for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; + rn = bgp_route_next(rn)) + if ((table = (rn->info)) != NULL) + bgp_announce_table (peer, afi, safi, table); +} + +void +bgp_announce_route_all (struct peer *peer) +{ + afi_t afi; + safi_t safi; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + bgp_announce_route (peer, afi, safi); +} + +static void +bgp_soft_reconfig_table (struct peer *peer, afi_t afi, safi_t safi, + struct bgp_table *table) +{ + int ret; + struct bgp_node *rn; + struct bgp_adj_in *ain; + + if (! table) + table = peer->bgp->rib[afi][safi]; + + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + for (ain = rn->adj_in; ain; ain = ain->next) + { + if (ain->peer == peer) + { + ret = bgp_update (peer, &rn->p, ain->attr, afi, safi, + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, + NULL, NULL, 1); + if (ret < 0) + { + bgp_unlock_node (rn); + return; + } + continue; + } + } +} + +void +bgp_soft_reconfig_in (struct peer *peer, afi_t afi, safi_t safi) +{ + struct bgp_node *rn; + struct bgp_table *table; + + if (peer->status != Established) + return; + + if (safi != SAFI_MPLS_VPN) + bgp_soft_reconfig_table (peer, afi, safi, NULL); + else + for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; + rn = bgp_route_next (rn)) + if ((table = rn->info) != NULL) + bgp_soft_reconfig_table (peer, afi, safi, table); +} + +static void +bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi, + struct bgp_table *table) +{ + struct bgp_node *rn; + struct bgp_adj_in *ain; + struct bgp_adj_out *aout; + struct bgp_info *ri; + + if (! table) + table = peer->bgp->rib[afi][safi]; + + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + { + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == peer) + { + bgp_rib_remove (rn, ri, peer, afi, safi); + break; + } + for (ain = rn->adj_in; ain; ain = ain->next) + if (ain->peer == peer) + { + bgp_adj_in_remove (rn, ain); + bgp_unlock_node (rn); + break; + } + for (aout = rn->adj_out; aout; aout = aout->next) + if (aout->peer == peer) + { + bgp_adj_out_remove (rn, aout, peer, afi, safi); + bgp_unlock_node (rn); + break; + } + } +} + +void +bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi) +{ + struct bgp_node *rn; + struct bgp_table *table; + + if (! peer->afc[afi][safi]) + return; + + if (safi != SAFI_MPLS_VPN) + bgp_clear_route_table (peer, afi, safi, NULL); + else + for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; + rn = bgp_route_next (rn)) + if ((table = rn->info) != NULL) + bgp_clear_route_table (peer, afi, safi, table); +} + +void +bgp_clear_route_all (struct peer *peer) +{ + afi_t afi; + safi_t safi; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + bgp_clear_route (peer, afi, safi); +} + +void +bgp_clear_adj_in (struct peer *peer, afi_t afi, safi_t safi) +{ + struct bgp_table *table; + struct bgp_node *rn; + struct bgp_adj_in *ain; + + table = peer->bgp->rib[afi][safi]; + + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + for (ain = rn->adj_in; ain ; ain = ain->next) + if (ain->peer == peer) + { + bgp_adj_in_remove (rn, ain); + bgp_unlock_node (rn); + break; + } +} + +/* Delete all kernel routes. */ +void +bgp_terminate () +{ + struct bgp *bgp; + struct listnode *nn; + struct bgp_node *rn; + struct bgp_table *table; + struct bgp_info *ri; + + LIST_LOOP (bm->bgp, bgp, nn) + { + table = bgp->rib[AFI_IP][SAFI_UNICAST]; + + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + for (ri = rn->info; ri; ri = ri->next) + if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) + && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_NORMAL) + bgp_zebra_withdraw (&rn->p, ri); + + table = bgp->rib[AFI_IP6][SAFI_UNICAST]; + + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + for (ri = rn->info; ri; ri = ri->next) + if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) + && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_NORMAL) + bgp_zebra_withdraw (&rn->p, ri); + } +} + +void +bgp_reset () +{ + vty_reset (); + bgp_zclient_reset (); + access_list_reset (); + prefix_list_reset (); +} + +/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr + value. */ +int +bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet) +{ + u_char *pnt; + u_char *lim; + struct prefix p; + int psize; + int ret; + + /* Check peer status. */ + if (peer->status != Established) + return 0; + + pnt = packet->nlri; + lim = pnt + packet->length; + + for (; pnt < lim; pnt += psize) + { + /* Clear prefix structure. */ + memset (&p, 0, sizeof (struct prefix)); + + /* Fetch prefix length. */ + p.prefixlen = *pnt++; + p.family = afi2family (packet->afi); + + /* Already checked in nlri_sanity_check(). We do double check + here. */ + if ((packet->afi == AFI_IP && p.prefixlen > 32) + || (packet->afi == AFI_IP6 && p.prefixlen > 128)) + return -1; + + /* Packet size overflow check. */ + psize = PSIZE (p.prefixlen); + + /* When packet overflow occur return immediately. */ + if (pnt + psize > lim) + return -1; + + /* Fetch prefix from NLRI packet. */ + memcpy (&p.u.prefix, pnt, psize); + + /* Check address. */ + if (packet->afi == AFI_IP && packet->safi == SAFI_UNICAST) + { + if (IN_CLASSD (ntohl (p.u.prefix4.s_addr))) + { + zlog (peer->log, LOG_ERR, + "IPv4 unicast NLRI is multicast address %s", + inet_ntoa (p.u.prefix4)); + bgp_notify_send (peer, + BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_INVAL_NETWORK); + return -1; + } + } + +#ifdef HAVE_IPV6 + /* Check address. */ + if (packet->afi == AFI_IP6 && packet->safi == SAFI_UNICAST) + { + if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) + { + char buf[BUFSIZ]; + + zlog (peer->log, LOG_WARNING, + "IPv6 link-local NLRI received %s ignore this NLRI", + inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ)); + + continue; + } + } +#endif /* HAVE_IPV6 */ + + /* Normal process. */ + if (attr) + ret = bgp_update (peer, &p, attr, packet->afi, packet->safi, + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0); + else + ret = bgp_withdraw (peer, &p, attr, packet->afi, packet->safi, + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL); + + /* Address family configuration mismatch or maximum-prefix count + overflow. */ + if (ret < 0) + return -1; + } + + /* Packet length consistency check. */ + if (pnt != lim) + return -1; + + return 0; +} + +/* NLRI encode syntax check routine. */ +int +bgp_nlri_sanity_check (struct peer *peer, int afi, u_char *pnt, + bgp_size_t length) +{ + u_char *end; + u_char prefixlen; + int psize; + + end = pnt + length; + + /* RFC1771 6.3 The NLRI field in the UPDATE message is checked for + syntactic validity. If the field is syntactically incorrect, + then the Error Subcode is set to Invalid Network Field. */ + + while (pnt < end) + { + prefixlen = *pnt++; + + /* Prefix length check. */ + if ((afi == AFI_IP && prefixlen > 32) + || (afi == AFI_IP6 && prefixlen > 128)) + { + plog_err (peer->log, + "%s [Error] Update packet error (wrong prefix length %d)", + peer->host, prefixlen); + bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_INVAL_NETWORK); + return -1; + } + + /* Packet size overflow check. */ + psize = PSIZE (prefixlen); + + if (pnt + psize > end) + { + plog_err (peer->log, + "%s [Error] Update packet error" + " (prefix data overflow prefix size is %d)", + peer->host, psize); + bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_INVAL_NETWORK); + return -1; + } + + pnt += psize; + } + + /* Packet length consistency check. */ + if (pnt != end) + { + plog_err (peer->log, + "%s [Error] Update packet error" + " (prefix length mismatch with total length)", + peer->host); + bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_INVAL_NETWORK); + return -1; + } + return 0; +} + +struct bgp_static * +bgp_static_new () +{ + struct bgp_static *new; + new = XMALLOC (MTYPE_BGP_STATIC, sizeof (struct bgp_static)); + memset (new, 0, sizeof (struct bgp_static)); + return new; +} + +void +bgp_static_free (struct bgp_static *bgp_static) +{ + if (bgp_static->rmap.name) + free (bgp_static->rmap.name); + XFREE (MTYPE_BGP_STATIC, bgp_static); +} + +void +bgp_static_update (struct bgp *bgp, struct prefix *p, + struct bgp_static *bgp_static, afi_t afi, safi_t safi) +{ + struct bgp_node *rn; + struct bgp_info *ri; + struct bgp_info *new; + struct bgp_info info; + struct attr attr; + struct attr *attr_new; + int ret; + + rn = bgp_afi_node_get (bgp, afi, safi, p, NULL); + + bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); + if (bgp_static) + { + attr.nexthop = bgp_static->igpnexthop; + attr.med = bgp_static->igpmetric; + attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); + } + + /* Apply route-map. */ + if (bgp_static->rmap.name) + { + info.peer = bgp->peer_self; + info.attr = &attr; + + ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info); + if (ret == RMAP_DENYMATCH) + { + /* Free uninterned attribute. */ + bgp_attr_flush (&attr); + + /* Unintern original. */ + aspath_unintern (attr.aspath); + bgp_static_withdraw (bgp, p, afi, safi); + return; + } + } + + attr_new = bgp_attr_intern (&attr); + + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_STATIC) + break; + + if (ri) + { + if (attrhash_cmp (ri->attr, attr_new)) + { + bgp_unlock_node (rn); + bgp_attr_unintern (attr_new); + aspath_unintern (attr.aspath); + return; + } + else + { + /* The attribute is changed. */ + SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED); + + /* Rewrite BGP route information. */ + bgp_aggregate_decrement (bgp, p, ri, afi, safi); + bgp_attr_unintern (ri->attr); + ri->attr = attr_new; + ri->uptime = time (NULL); + + /* Process change. */ + bgp_aggregate_increment (bgp, p, ri, afi, safi); + bgp_process (bgp, rn, afi, safi); + bgp_unlock_node (rn); + aspath_unintern (attr.aspath); + return; + } + } + + /* Make new BGP info. */ + new = bgp_info_new (); + new->type = ZEBRA_ROUTE_BGP; + new->sub_type = BGP_ROUTE_STATIC; + new->peer = bgp->peer_self; + SET_FLAG (new->flags, BGP_INFO_VALID); + new->attr = attr_new; + new->uptime = time (NULL); + + /* Aggregate address increment. */ + bgp_aggregate_increment (bgp, p, new, afi, safi); + + /* Register new BGP information. */ + bgp_info_add (rn, new); + + /* Process change. */ + bgp_process (bgp, rn, afi, safi); + + /* Unintern original. */ + aspath_unintern (attr.aspath); +} + +void +bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi, + u_char safi, struct prefix_rd *prd, u_char *tag) +{ + struct bgp_node *rn; + struct bgp_info *new; + + rn = bgp_afi_node_get (bgp, afi, safi, p, prd); + + /* Make new BGP info. */ + new = bgp_info_new (); + new->type = ZEBRA_ROUTE_BGP; + new->sub_type = BGP_ROUTE_STATIC; + new->peer = bgp->peer_self; + new->attr = bgp_attr_default_intern (BGP_ORIGIN_IGP); + SET_FLAG (new->flags, BGP_INFO_VALID); + new->uptime = time (NULL); + memcpy (new->tag, tag, 3); + + /* Aggregate address increment. */ + bgp_aggregate_increment (bgp, p, (struct bgp_info *) new, afi, safi); + + /* Register new BGP information. */ + bgp_info_add (rn, (struct bgp_info *) new); + + /* Process change. */ + bgp_process (bgp, rn, afi, safi); +} + +void +bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi, + safi_t safi) +{ + struct bgp_node *rn; + struct bgp_info *ri; + + rn = bgp_afi_node_get (bgp, afi, safi, p, NULL); + + /* Check selected route and self inserted route. */ + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self + && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_STATIC) + break; + + /* Withdraw static BGP route from routing table. */ + if (ri) + { + bgp_aggregate_decrement (bgp, p, ri, afi, safi); + UNSET_FLAG (ri->flags, BGP_INFO_VALID); + bgp_process (bgp, rn, afi, safi); + bgp_info_delete (rn, ri); + bgp_info_free (ri); + bgp_unlock_node (rn); + } + + /* Unlock bgp_node_lookup. */ + bgp_unlock_node (rn); +} + +void +bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi, + u_char safi, struct prefix_rd *prd, u_char *tag) +{ + struct bgp_node *rn; + struct bgp_info *ri; + + rn = bgp_afi_node_get (bgp, afi, safi, p, prd); + + /* Check selected route and self inserted route. */ + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self + && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_STATIC) + break; + + /* Withdraw static BGP route from routing table. */ + if (ri) + { + bgp_aggregate_decrement (bgp, p, ri, afi, safi); + UNSET_FLAG (ri->flags, BGP_INFO_VALID); + bgp_process (bgp, rn, afi, safi); + bgp_info_delete (rn, ri); + bgp_info_free (ri); + bgp_unlock_node (rn); + } + + /* Unlock bgp_node_lookup. */ + bgp_unlock_node (rn); +} + +/* Configure static BGP network. When user don't run zebra, static + route should be installed as valid. */ +int +bgp_static_set (struct vty *vty, struct bgp *bgp, char *ip_str, u_int16_t afi, + u_char safi, char *rmap, int backdoor) +{ + int ret; + struct prefix p; + struct bgp_static *bgp_static; + struct bgp_node *rn; + int need_update = 0; + + /* Convert IP prefix string to struct prefix. */ + ret = str2prefix (ip_str, &p); + if (! ret) + { + vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } +#ifdef HAVE_IPV6 + if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) + { + vty_out (vty, "%% Malformed prefix (link-local address)%s", + VTY_NEWLINE); + return CMD_WARNING; + } +#endif /* HAVE_IPV6 */ + + apply_mask (&p); + + /* Set BGP static route configuration. */ + rn = bgp_node_get (bgp->route[afi][safi], &p); + + if (rn->info) + { + /* Configuration change. */ + bgp_static = rn->info; + + /* Check previous routes are installed into BGP. */ + if (! bgp_static->backdoor && bgp_static->valid) + need_update = 1; + + bgp_static->backdoor = backdoor; + if (rmap) + { + if (bgp_static->rmap.name) + free (bgp_static->rmap.name); + bgp_static->rmap.name = strdup (rmap); + bgp_static->rmap.map = route_map_lookup_by_name (rmap); + } + else + { + if (bgp_static->rmap.name) + free (bgp_static->rmap.name); + bgp_static->rmap.name = NULL; + bgp_static->rmap.map = NULL; + bgp_static->valid = 0; + } + bgp_unlock_node (rn); + } + else + { + /* New configuration. */ + bgp_static = bgp_static_new (); + bgp_static->backdoor = backdoor; + bgp_static->valid = 0; + bgp_static->igpmetric = 0; + bgp_static->igpnexthop.s_addr = 0; + if (rmap) + { + if (bgp_static->rmap.name) + free (bgp_static->rmap.name); + bgp_static->rmap.name = strdup (rmap); + bgp_static->rmap.map = route_map_lookup_by_name (rmap); + } + rn->info = bgp_static; + } + + /* If BGP scan is not enabled, we should install this route here. */ + if (! bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)) + { + bgp_static->valid = 1; + + if (need_update) + bgp_static_withdraw (bgp, &p, afi, safi); + + if (! bgp_static->backdoor) + bgp_static_update (bgp, &p, bgp_static, afi, safi); + } + + return CMD_SUCCESS; +} + +/* Configure static BGP network. */ +int +bgp_static_unset (struct vty *vty, struct bgp *bgp, char *ip_str, + u_int16_t afi, u_char safi) +{ + int ret; + struct prefix p; + struct bgp_static *bgp_static; + struct bgp_node *rn; + + /* Convert IP prefix string to struct prefix. */ + ret = str2prefix (ip_str, &p); + if (! ret) + { + vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } +#ifdef HAVE_IPV6 + if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) + { + vty_out (vty, "%% Malformed prefix (link-local address)%s", + VTY_NEWLINE); + return CMD_WARNING; + } +#endif /* HAVE_IPV6 */ + + apply_mask (&p); + + rn = bgp_node_lookup (bgp->route[afi][safi], &p); + if (! rn) + { + vty_out (vty, "%% Can't find specified static route configuration.%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + bgp_static = rn->info; + + /* Update BGP RIB. */ + if (! bgp_static->backdoor) + bgp_static_withdraw (bgp, &p, afi, safi); + + /* Clear configuration. */ + bgp_static_free (bgp_static); + rn->info = NULL; + bgp_unlock_node (rn); + bgp_unlock_node (rn); + + return CMD_SUCCESS; +} + +/* Called from bgp_delete(). Delete all static routes from the BGP + instance. */ +void +bgp_static_delete (struct bgp *bgp) +{ + afi_t afi; + safi_t safi; + struct bgp_node *rn; + struct bgp_node *rm; + struct bgp_table *table; + struct bgp_static *bgp_static; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) + if (rn->info != NULL) + { + if (safi == SAFI_MPLS_VPN) + { + table = rn->info; + + for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) + { + bgp_static = rn->info; + bgp_static_withdraw_vpnv4 (bgp, &rm->p, + AFI_IP, SAFI_MPLS_VPN, + (struct prefix_rd *)&rn->p, + bgp_static->tag); + bgp_static_free (bgp_static); + rn->info = NULL; + bgp_unlock_node (rn); + } + } + else + { + bgp_static = rn->info; + bgp_static_withdraw (bgp, &rn->p, afi, safi); + bgp_static_free (bgp_static); + rn->info = NULL; + bgp_unlock_node (rn); + } + } +} + +int +bgp_static_set_vpnv4 (struct vty *vty, char *ip_str, char *rd_str, + char *tag_str) +{ + int ret; + struct prefix p; + struct prefix_rd prd; + struct bgp *bgp; + struct bgp_node *prn; + struct bgp_node *rn; + struct bgp_table *table; + struct bgp_static *bgp_static; + u_char tag[3]; + + bgp = vty->index; + + ret = str2prefix (ip_str, &p); + if (! ret) + { + vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + apply_mask (&p); + + ret = str2prefix_rd (rd_str, &prd); + if (! ret) + { + vty_out (vty, "%% Malformed rd%s", VTY_NEWLINE); + return CMD_WARNING; + } + + ret = str2tag (tag_str, tag); + if (! ret) + { + vty_out (vty, "%% Malformed tag%s", VTY_NEWLINE); + return CMD_WARNING; + } + + prn = bgp_node_get (bgp->route[AFI_IP][SAFI_MPLS_VPN], + (struct prefix *)&prd); + if (prn->info == NULL) + prn->info = bgp_table_init (); + else + bgp_unlock_node (prn); + table = prn->info; + + rn = bgp_node_get (table, &p); + + if (rn->info) + { + vty_out (vty, "%% Same network configuration exists%s", VTY_NEWLINE); + bgp_unlock_node (rn); + } + else + { + /* New configuration. */ + bgp_static = bgp_static_new (); + bgp_static->valid = 1; + memcpy (bgp_static->tag, tag, 3); + rn->info = bgp_static; + + bgp_static_update_vpnv4 (bgp, &p, AFI_IP, SAFI_MPLS_VPN, &prd, tag); + } + + return CMD_SUCCESS; +} + +/* Configure static BGP network. */ +int +bgp_static_unset_vpnv4 (struct vty *vty, char *ip_str, char *rd_str, + char *tag_str) +{ + int ret; + struct bgp *bgp; + struct prefix p; + struct prefix_rd prd; + struct bgp_node *prn; + struct bgp_node *rn; + struct bgp_table *table; + struct bgp_static *bgp_static; + u_char tag[3]; + + bgp = vty->index; + + /* Convert IP prefix string to struct prefix. */ + ret = str2prefix (ip_str, &p); + if (! ret) + { + vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + apply_mask (&p); + + ret = str2prefix_rd (rd_str, &prd); + if (! ret) + { + vty_out (vty, "%% Malformed rd%s", VTY_NEWLINE); + return CMD_WARNING; + } + + ret = str2tag (tag_str, tag); + if (! ret) + { + vty_out (vty, "%% Malformed tag%s", VTY_NEWLINE); + return CMD_WARNING; + } + + prn = bgp_node_get (bgp->route[AFI_IP][SAFI_MPLS_VPN], + (struct prefix *)&prd); + if (prn->info == NULL) + prn->info = bgp_table_init (); + else + bgp_unlock_node (prn); + table = prn->info; + + rn = bgp_node_lookup (table, &p); + + if (rn) + { + bgp_static_withdraw_vpnv4 (bgp, &p, AFI_IP, SAFI_MPLS_VPN, &prd, tag); + + bgp_static = rn->info; + bgp_static_free (bgp_static); + rn->info = NULL; + bgp_unlock_node (rn); + bgp_unlock_node (rn); + } + else + vty_out (vty, "%% Can't find the route%s", VTY_NEWLINE); + + return CMD_SUCCESS; +} + +DEFUN (bgp_network, + bgp_network_cmd, + "network A.B.C.D/M", + "Specify a network to announce via BGP\n" + "IP prefix /, e.g., 35.0.0.0/8\n") +{ + return bgp_static_set (vty, vty->index, argv[0], + AFI_IP, bgp_node_safi (vty), NULL, 0); +} + +DEFUN (bgp_network_route_map, + bgp_network_route_map_cmd, + "network A.B.C.D/M route-map WORD", + "Specify a network to announce via BGP\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Route-map to modify the attributes\n" + "Name of the route map\n") +{ + return bgp_static_set (vty, vty->index, argv[0], + AFI_IP, bgp_node_safi (vty), argv[1], 0); +} + +DEFUN (bgp_network_backdoor, + bgp_network_backdoor_cmd, + "network A.B.C.D/M backdoor", + "Specify a network to announce via BGP\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Specify a BGP backdoor route\n") +{ + return bgp_static_set (vty, vty->index, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1); +} + +DEFUN (bgp_network_mask, + bgp_network_mask_cmd, + "network A.B.C.D mask A.B.C.D", + "Specify a network to announce via BGP\n" + "Network number\n" + "Network mask\n" + "Network mask\n") +{ + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str); + if (! ret) + { + vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_static_set (vty, vty->index, prefix_str, + AFI_IP, bgp_node_safi (vty), NULL, 0); +} + +DEFUN (bgp_network_mask_route_map, + bgp_network_mask_route_map_cmd, + "network A.B.C.D mask A.B.C.D route-map WORD", + "Specify a network to announce via BGP\n" + "Network number\n" + "Network mask\n" + "Network mask\n" + "Route-map to modify the attributes\n" + "Name of the route map\n") +{ + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str); + if (! ret) + { + vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_static_set (vty, vty->index, prefix_str, + AFI_IP, bgp_node_safi (vty), argv[2], 0); +} + +DEFUN (bgp_network_mask_backdoor, + bgp_network_mask_backdoor_cmd, + "network A.B.C.D mask A.B.C.D backdoor", + "Specify a network to announce via BGP\n" + "Network number\n" + "Network mask\n" + "Network mask\n" + "Specify a BGP backdoor route\n") +{ + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str); + if (! ret) + { + vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_static_set (vty, vty->index, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1); +} + +DEFUN (bgp_network_mask_natural, + bgp_network_mask_natural_cmd, + "network A.B.C.D", + "Specify a network to announce via BGP\n" + "Network number\n") +{ + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str (argv[0], NULL, prefix_str); + if (! ret) + { + vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_static_set (vty, vty->index, prefix_str, + AFI_IP, bgp_node_safi (vty), NULL, 0); +} + +DEFUN (bgp_network_mask_natural_route_map, + bgp_network_mask_natural_route_map_cmd, + "network A.B.C.D route-map WORD", + "Specify a network to announce via BGP\n" + "Network number\n" + "Route-map to modify the attributes\n" + "Name of the route map\n") +{ + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str (argv[0], NULL, prefix_str); + if (! ret) + { + vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_static_set (vty, vty->index, prefix_str, + AFI_IP, bgp_node_safi (vty), argv[1], 0); +} + +DEFUN (bgp_network_mask_natural_backdoor, + bgp_network_mask_natural_backdoor_cmd, + "network A.B.C.D backdoor", + "Specify a network to announce via BGP\n" + "Network number\n" + "Specify a BGP backdoor route\n") +{ + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str (argv[0], NULL, prefix_str); + if (! ret) + { + vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_static_set (vty, vty->index, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1); +} + +DEFUN (no_bgp_network, + no_bgp_network_cmd, + "no network A.B.C.D/M", + NO_STR + "Specify a network to announce via BGP\n" + "IP prefix /, e.g., 35.0.0.0/8\n") +{ + return bgp_static_unset (vty, vty->index, argv[0], AFI_IP, + bgp_node_safi (vty)); +} + +ALIAS (no_bgp_network, + no_bgp_network_route_map_cmd, + "no network A.B.C.D/M route-map WORD", + NO_STR + "Specify a network to announce via BGP\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Route-map to modify the attributes\n" + "Name of the route map\n") + +ALIAS (no_bgp_network, + no_bgp_network_backdoor_cmd, + "no network A.B.C.D/M backdoor", + NO_STR + "Specify a network to announce via BGP\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Specify a BGP backdoor route\n") + +DEFUN (no_bgp_network_mask, + no_bgp_network_mask_cmd, + "no network A.B.C.D mask A.B.C.D", + NO_STR + "Specify a network to announce via BGP\n" + "Network number\n" + "Network mask\n" + "Network mask\n") +{ + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str); + if (! ret) + { + vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_static_unset (vty, vty->index, prefix_str, AFI_IP, + bgp_node_safi (vty)); +} + +ALIAS (no_bgp_network_mask, + no_bgp_network_mask_route_map_cmd, + "no network A.B.C.D mask A.B.C.D route-map WORD", + NO_STR + "Specify a network to announce via BGP\n" + "Network number\n" + "Network mask\n" + "Network mask\n" + "Route-map to modify the attributes\n" + "Name of the route map\n") + +ALIAS (no_bgp_network_mask, + no_bgp_network_mask_backdoor_cmd, + "no network A.B.C.D mask A.B.C.D backdoor", + NO_STR + "Specify a network to announce via BGP\n" + "Network number\n" + "Network mask\n" + "Network mask\n" + "Specify a BGP backdoor route\n") + +DEFUN (no_bgp_network_mask_natural, + no_bgp_network_mask_natural_cmd, + "no network A.B.C.D", + NO_STR + "Specify a network to announce via BGP\n" + "Network number\n") +{ + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str (argv[0], NULL, prefix_str); + if (! ret) + { + vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_static_unset (vty, vty->index, prefix_str, AFI_IP, + bgp_node_safi (vty)); +} + +ALIAS (no_bgp_network_mask_natural, + no_bgp_network_mask_natural_route_map_cmd, + "no network A.B.C.D route-map WORD", + NO_STR + "Specify a network to announce via BGP\n" + "Network number\n" + "Route-map to modify the attributes\n" + "Name of the route map\n") + +ALIAS (no_bgp_network_mask_natural, + no_bgp_network_mask_natural_backdoor_cmd, + "no network A.B.C.D backdoor", + NO_STR + "Specify a network to announce via BGP\n" + "Network number\n" + "Specify a BGP backdoor route\n") + +#ifdef HAVE_IPV6 +DEFUN (ipv6_bgp_network, + ipv6_bgp_network_cmd, + "network X:X::X:X/M", + "Specify a network to announce via BGP\n" + "IPv6 prefix /\n") +{ + return bgp_static_set (vty, vty->index, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0); +} + +DEFUN (ipv6_bgp_network_route_map, + ipv6_bgp_network_route_map_cmd, + "network X:X::X:X/M route-map WORD", + "Specify a network to announce via BGP\n" + "IPv6 prefix /\n" + "Route-map to modify the attributes\n" + "Name of the route map\n") +{ + return bgp_static_set (vty, vty->index, argv[0], AFI_IP6, + bgp_node_safi (vty), argv[1], 0); +} + +DEFUN (no_ipv6_bgp_network, + no_ipv6_bgp_network_cmd, + "no network X:X::X:X/M", + NO_STR + "Specify a network to announce via BGP\n" + "IPv6 prefix /\n") +{ + return bgp_static_unset (vty, vty->index, argv[0], AFI_IP6, SAFI_UNICAST); +} + +ALIAS (no_ipv6_bgp_network, + no_ipv6_bgp_network_route_map_cmd, + "no network X:X::X:X/M route-map WORD", + NO_STR + "Specify a network to announce via BGP\n" + "IPv6 prefix /\n" + "Route-map to modify the attributes\n" + "Name of the route map\n") + +ALIAS (ipv6_bgp_network, + old_ipv6_bgp_network_cmd, + "ipv6 bgp network X:X::X:X/M", + IPV6_STR + BGP_STR + "Specify a network to announce via BGP\n" + "IPv6 prefix /, e.g., 3ffe::/16\n") + +ALIAS (no_ipv6_bgp_network, + old_no_ipv6_bgp_network_cmd, + "no ipv6 bgp network X:X::X:X/M", + NO_STR + IPV6_STR + BGP_STR + "Specify a network to announce via BGP\n" + "IPv6 prefix /, e.g., 3ffe::/16\n") +#endif /* HAVE_IPV6 */ + +/* Aggreagete address: + + advertise-map Set condition to advertise attribute + as-set Generate AS set path information + attribute-map Set attributes of aggregate + route-map Set parameters of aggregate + summary-only Filter more specific routes from updates + suppress-map Conditionally filter more specific routes from updates + + */ +struct bgp_aggregate +{ + /* Summary-only flag. */ + u_char summary_only; + + /* AS set generation. */ + u_char as_set; + + /* Route-map for aggregated route. */ + struct route_map *map; + + /* Suppress-count. */ + unsigned long count; + + /* SAFI configuration. */ + safi_t safi; +}; + +struct bgp_aggregate * +bgp_aggregate_new () +{ + struct bgp_aggregate *new; + new = XMALLOC (MTYPE_BGP_AGGREGATE, sizeof (struct bgp_aggregate)); + memset (new, 0, sizeof (struct bgp_aggregate)); + return new; +} + +void +bgp_aggregate_free (struct bgp_aggregate *aggregate) +{ + XFREE (MTYPE_BGP_AGGREGATE, aggregate); +} + +void +bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew, + afi_t afi, safi_t safi, struct bgp_info *del, + struct bgp_aggregate *aggregate) +{ + struct bgp_table *table; + struct bgp_node *top; + struct bgp_node *rn; + u_char origin; + struct aspath *aspath = NULL; + struct aspath *asmerge = NULL; + struct community *community = NULL; + struct community *commerge = NULL; + struct in_addr nexthop; + u_int32_t med = 0; + struct bgp_info *ri; + struct bgp_info *new; + int first = 1; + unsigned long match = 0; + + /* Record adding route's nexthop and med. */ + if (rinew) + { + nexthop = rinew->attr->nexthop; + med = rinew->attr->med; + } + + /* ORIGIN attribute: If at least one route among routes that are + aggregated has ORIGIN with the value INCOMPLETE, then the + aggregated route must have the ORIGIN attribute with the value + INCOMPLETE. Otherwise, if at least one route among routes that + are aggregated has ORIGIN with the value EGP, then the aggregated + route must have the origin attribute with the value EGP. In all + other case the value of the ORIGIN attribute of the aggregated + route is INTERNAL. */ + origin = BGP_ORIGIN_IGP; + + table = bgp->rib[afi][safi]; + + top = bgp_node_get (table, p); + for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top)) + if (rn->p.prefixlen > p->prefixlen) + { + match = 0; + + for (ri = rn->info; ri; ri = ri->next) + { + if (BGP_INFO_HOLDDOWN (ri)) + continue; + + if (del && ri == del) + continue; + + if (! rinew && first) + { + nexthop = ri->attr->nexthop; + med = ri->attr->med; + first = 0; + } + +#ifdef AGGREGATE_NEXTHOP_CHECK + if (! IPV4_ADDR_SAME (&ri->attr->nexthop, &nexthop) + || ri->attr->med != med) + { + if (aspath) + aspath_free (aspath); + if (community) + community_free (community); + bgp_unlock_node (rn); + bgp_unlock_node (top); + return; + } +#endif /* AGGREGATE_NEXTHOP_CHECK */ + + if (ri->sub_type != BGP_ROUTE_AGGREGATE) + { + if (aggregate->summary_only) + { + ri->suppress++; + SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED); + match++; + } + + aggregate->count++; + + if (aggregate->as_set) + { + if (origin < ri->attr->origin) + origin = ri->attr->origin; + + if (aspath) + { + asmerge = aspath_aggregate (aspath, ri->attr->aspath); + aspath_free (aspath); + aspath = asmerge; + } + else + aspath = aspath_dup (ri->attr->aspath); + + if (ri->attr->community) + { + if (community) + { + commerge = community_merge (community, + ri->attr->community); + community = community_uniq_sort (commerge); + community_free (commerge); + } + else + community = community_dup (ri->attr->community); + } + } + } + } + if (match) + bgp_process (bgp, rn, afi, safi); + } + bgp_unlock_node (top); + + if (rinew) + { + aggregate->count++; + + if (aggregate->summary_only) + rinew->suppress++; + + if (aggregate->as_set) + { + if (origin < rinew->attr->origin) + origin = rinew->attr->origin; + + if (aspath) + { + asmerge = aspath_aggregate (aspath, rinew->attr->aspath); + aspath_free (aspath); + aspath = asmerge; + } + else + aspath = aspath_dup (rinew->attr->aspath); + + if (rinew->attr->community) + { + if (community) + { + commerge = community_merge (community, + rinew->attr->community); + community = community_uniq_sort (commerge); + community_free (commerge); + } + else + community = community_dup (rinew->attr->community); + } + } + } + + if (aggregate->count > 0) + { + rn = bgp_node_get (table, p); + new = bgp_info_new (); + new->type = ZEBRA_ROUTE_BGP; + new->sub_type = BGP_ROUTE_AGGREGATE; + new->peer = bgp->peer_self; + SET_FLAG (new->flags, BGP_INFO_VALID); + new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set); + new->uptime = time (NULL); + + bgp_info_add (rn, new); + bgp_process (bgp, rn, afi, safi); + } + else + { + if (aspath) + aspath_free (aspath); + if (community) + community_free (community); + } +} + +void bgp_aggregate_delete (struct bgp *, struct prefix *, afi_t, safi_t, + struct bgp_aggregate *); + +void +bgp_aggregate_increment (struct bgp *bgp, struct prefix *p, + struct bgp_info *ri, afi_t afi, safi_t safi) +{ + struct bgp_node *child; + struct bgp_node *rn; + struct bgp_aggregate *aggregate; + + /* MPLS-VPN aggregation is not yet supported. */ + if (safi == SAFI_MPLS_VPN) + return; + + if (p->prefixlen == 0) + return; + + if (BGP_INFO_HOLDDOWN (ri)) + return; + + child = bgp_node_get (bgp->aggregate[afi][safi], p); + + /* Aggregate address configuration check. */ + for (rn = child; rn; rn = rn->parent) + if ((aggregate = rn->info) != NULL && rn->p.prefixlen < p->prefixlen) + { + bgp_aggregate_delete (bgp, &rn->p, afi, safi, aggregate); + bgp_aggregate_route (bgp, &rn->p, ri, safi, safi, NULL, aggregate); + } + bgp_unlock_node (child); +} + +void +bgp_aggregate_decrement (struct bgp *bgp, struct prefix *p, + struct bgp_info *del, afi_t afi, safi_t safi) +{ + struct bgp_node *child; + struct bgp_node *rn; + struct bgp_aggregate *aggregate; + + /* MPLS-VPN aggregation is not yet supported. */ + if (safi == SAFI_MPLS_VPN) + return; + + if (p->prefixlen == 0) + return; + + child = bgp_node_get (bgp->aggregate[afi][safi], p); + + /* Aggregate address configuration check. */ + for (rn = child; rn; rn = rn->parent) + if ((aggregate = rn->info) != NULL && rn->p.prefixlen < p->prefixlen) + { + bgp_aggregate_delete (bgp, &rn->p, afi, safi, aggregate); + bgp_aggregate_route (bgp, &rn->p, NULL, safi, safi, del, aggregate); + } + bgp_unlock_node (child); +} + +void +bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, + struct bgp_aggregate *aggregate) +{ + struct bgp_table *table; + struct bgp_node *top; + struct bgp_node *rn; + struct bgp_info *new; + struct bgp_info *ri; + unsigned long match; + u_char origin = BGP_ORIGIN_IGP; + struct aspath *aspath = NULL; + struct aspath *asmerge = NULL; + struct community *community = NULL; + struct community *commerge = NULL; + + table = bgp->rib[afi][safi]; + + /* Sanity check. */ + if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN) + return; + if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN) + return; + + /* If routes exists below this node, generate aggregate routes. */ + top = bgp_node_get (table, p); + for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top)) + if (rn->p.prefixlen > p->prefixlen) + { + match = 0; + + for (ri = rn->info; ri; ri = ri->next) + { + if (BGP_INFO_HOLDDOWN (ri)) + continue; + + if (ri->sub_type != BGP_ROUTE_AGGREGATE) + { + /* summary-only aggregate route suppress aggregated + route announcement. */ + if (aggregate->summary_only) + { + ri->suppress++; + SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED); + match++; + } + /* as-set aggregate route generate origin, as path, + community aggregation. */ + if (aggregate->as_set) + { + if (origin < ri->attr->origin) + origin = ri->attr->origin; + + if (aspath) + { + asmerge = aspath_aggregate (aspath, ri->attr->aspath); + aspath_free (aspath); + aspath = asmerge; + } + else + aspath = aspath_dup (ri->attr->aspath); + + if (ri->attr->community) + { + if (community) + { + commerge = community_merge (community, + ri->attr->community); + community = community_uniq_sort (commerge); + community_free (commerge); + } + else + community = community_dup (ri->attr->community); + } + } + aggregate->count++; + } + } + + /* If this node is suppressed, process the change. */ + if (match) + bgp_process (bgp, rn, afi, safi); + } + bgp_unlock_node (top); + + /* Add aggregate route to BGP table. */ + if (aggregate->count) + { + rn = bgp_node_get (table, p); + + new = bgp_info_new (); + new->type = ZEBRA_ROUTE_BGP; + new->sub_type = BGP_ROUTE_AGGREGATE; + new->peer = bgp->peer_self; + SET_FLAG (new->flags, BGP_INFO_VALID); + new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set); + new->uptime = time (NULL); + + bgp_info_add (rn, new); + + /* Process change. */ + bgp_process (bgp, rn, afi, safi); + } +} + +void +bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi, + safi_t safi, struct bgp_aggregate *aggregate) +{ + struct bgp_table *table; + struct bgp_node *top; + struct bgp_node *rn; + struct bgp_info *ri; + unsigned long match; + + table = bgp->rib[afi][safi]; + + if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN) + return; + if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN) + return; + + /* If routes exists below this node, generate aggregate routes. */ + top = bgp_node_get (table, p); + for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top)) + if (rn->p.prefixlen > p->prefixlen) + { + match = 0; + + for (ri = rn->info; ri; ri = ri->next) + { + if (BGP_INFO_HOLDDOWN (ri)) + continue; + + if (ri->sub_type != BGP_ROUTE_AGGREGATE) + { + if (aggregate->summary_only) + { + ri->suppress--; + + if (ri->suppress == 0) + { + SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED); + match++; + } + } + aggregate->count--; + } + } + + /* If this node is suppressed, process the change. */ + if (match) + bgp_process (bgp, rn, afi, safi); + } + bgp_unlock_node (top); + + /* Delete aggregate route from BGP table. */ + rn = bgp_node_get (table, p); + + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self + && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_AGGREGATE) + break; + + /* Withdraw static BGP route from routing table. */ + if (ri) + { + UNSET_FLAG (ri->flags, BGP_INFO_VALID); + bgp_process (bgp, rn, afi, safi); + bgp_info_delete (rn, ri); + bgp_info_free (ri); + bgp_unlock_node (rn); + } + + /* Unlock bgp_node_lookup. */ + bgp_unlock_node (rn); +} + +/* Aggregate route attribute. */ +#define AGGREGATE_SUMMARY_ONLY 1 +#define AGGREGATE_AS_SET 1 + +int +bgp_aggregate_set (struct vty *vty, char *prefix_str, afi_t afi, safi_t safi, + u_char summary_only, u_char as_set) +{ + int ret; + struct prefix p; + struct bgp_node *rn; + struct bgp *bgp; + struct bgp_aggregate *aggregate; + + /* Convert string to prefix structure. */ + ret = str2prefix (prefix_str, &p); + if (!ret) + { + vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + apply_mask (&p); + + /* Get BGP structure. */ + bgp = vty->index; + + /* Old configuration check. */ + rn = bgp_node_get (bgp->aggregate[afi][safi], &p); + + if (rn->info) + { + vty_out (vty, "There is already same aggregate network.%s", VTY_NEWLINE); + bgp_unlock_node (rn); + return CMD_WARNING; + } + + /* Make aggregate address structure. */ + aggregate = bgp_aggregate_new (); + aggregate->summary_only = summary_only; + aggregate->as_set = as_set; + aggregate->safi = safi; + rn->info = aggregate; + + /* Aggregate address insert into BGP routing table. */ + if (safi & SAFI_UNICAST) + bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate); + if (safi & SAFI_MULTICAST) + bgp_aggregate_add (bgp, &p, afi, SAFI_MULTICAST, aggregate); + + return CMD_SUCCESS; +} + +int +bgp_aggregate_unset (struct vty *vty, char *prefix_str, afi_t afi, safi_t safi) +{ + int ret; + struct prefix p; + struct bgp_node *rn; + struct bgp *bgp; + struct bgp_aggregate *aggregate; + + /* Convert string to prefix structure. */ + ret = str2prefix (prefix_str, &p); + if (!ret) + { + vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + apply_mask (&p); + + /* Get BGP structure. */ + bgp = vty->index; + + /* Old configuration check. */ + rn = bgp_node_lookup (bgp->aggregate[afi][safi], &p); + if (! rn) + { + vty_out (vty, "%% There is no aggregate-address configuration.%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + aggregate = rn->info; + if (aggregate->safi & SAFI_UNICAST) + bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate); + if (aggregate->safi & SAFI_MULTICAST) + bgp_aggregate_delete (bgp, &p, afi, SAFI_MULTICAST, aggregate); + + /* Unlock aggregate address configuration. */ + rn->info = NULL; + bgp_aggregate_free (aggregate); + bgp_unlock_node (rn); + bgp_unlock_node (rn); + + return CMD_SUCCESS; +} + +DEFUN (aggregate_address, + aggregate_address_cmd, + "aggregate-address A.B.C.D/M", + "Configure BGP aggregate entries\n" + "Aggregate prefix\n") +{ + return bgp_aggregate_set (vty, argv[0], AFI_IP, bgp_node_safi (vty), 0, 0); +} + +DEFUN (aggregate_address_mask, + aggregate_address_mask_cmd, + "aggregate-address A.B.C.D A.B.C.D", + "Configure BGP aggregate entries\n" + "Aggregate address\n" + "Aggregate mask\n") +{ + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str); + + if (! ret) + { + vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty), + 0, 0); +} + +DEFUN (aggregate_address_summary_only, + aggregate_address_summary_only_cmd, + "aggregate-address A.B.C.D/M summary-only", + "Configure BGP aggregate entries\n" + "Aggregate prefix\n" + "Filter more specific routes from updates\n") +{ + return bgp_aggregate_set (vty, argv[0], AFI_IP, bgp_node_safi (vty), + AGGREGATE_SUMMARY_ONLY, 0); +} + +DEFUN (aggregate_address_mask_summary_only, + aggregate_address_mask_summary_only_cmd, + "aggregate-address A.B.C.D A.B.C.D summary-only", + "Configure BGP aggregate entries\n" + "Aggregate address\n" + "Aggregate mask\n" + "Filter more specific routes from updates\n") +{ + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str); + + if (! ret) + { + vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty), + AGGREGATE_SUMMARY_ONLY, 0); +} + +DEFUN (aggregate_address_as_set, + aggregate_address_as_set_cmd, + "aggregate-address A.B.C.D/M as-set", + "Configure BGP aggregate entries\n" + "Aggregate prefix\n" + "Generate AS set path information\n") +{ + return bgp_aggregate_set (vty, argv[0], AFI_IP, bgp_node_safi (vty), + 0, AGGREGATE_AS_SET); +} + +DEFUN (aggregate_address_mask_as_set, + aggregate_address_mask_as_set_cmd, + "aggregate-address A.B.C.D A.B.C.D as-set", + "Configure BGP aggregate entries\n" + "Aggregate address\n" + "Aggregate mask\n" + "Generate AS set path information\n") +{ + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str); + + if (! ret) + { + vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty), + 0, AGGREGATE_AS_SET); +} + + +DEFUN (aggregate_address_as_set_summary, + aggregate_address_as_set_summary_cmd, + "aggregate-address A.B.C.D/M as-set summary-only", + "Configure BGP aggregate entries\n" + "Aggregate prefix\n" + "Generate AS set path information\n" + "Filter more specific routes from updates\n") +{ + return bgp_aggregate_set (vty, argv[0], AFI_IP, bgp_node_safi (vty), + AGGREGATE_SUMMARY_ONLY, AGGREGATE_AS_SET); +} + +ALIAS (aggregate_address_as_set_summary, + aggregate_address_summary_as_set_cmd, + "aggregate-address A.B.C.D/M summary-only as-set", + "Configure BGP aggregate entries\n" + "Aggregate prefix\n" + "Filter more specific routes from updates\n" + "Generate AS set path information\n") + +DEFUN (aggregate_address_mask_as_set_summary, + aggregate_address_mask_as_set_summary_cmd, + "aggregate-address A.B.C.D A.B.C.D as-set summary-only", + "Configure BGP aggregate entries\n" + "Aggregate address\n" + "Aggregate mask\n" + "Generate AS set path information\n" + "Filter more specific routes from updates\n") +{ + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str); + + if (! ret) + { + vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty), + AGGREGATE_SUMMARY_ONLY, AGGREGATE_AS_SET); +} + +ALIAS (aggregate_address_mask_as_set_summary, + aggregate_address_mask_summary_as_set_cmd, + "aggregate-address A.B.C.D A.B.C.D summary-only as-set", + "Configure BGP aggregate entries\n" + "Aggregate address\n" + "Aggregate mask\n" + "Filter more specific routes from updates\n" + "Generate AS set path information\n") + +DEFUN (no_aggregate_address, + no_aggregate_address_cmd, + "no aggregate-address A.B.C.D/M", + NO_STR + "Configure BGP aggregate entries\n" + "Aggregate prefix\n") +{ + return bgp_aggregate_unset (vty, argv[0], AFI_IP, bgp_node_safi (vty)); +} + +ALIAS (no_aggregate_address, + no_aggregate_address_summary_only_cmd, + "no aggregate-address A.B.C.D/M summary-only", + NO_STR + "Configure BGP aggregate entries\n" + "Aggregate prefix\n" + "Filter more specific routes from updates\n") + +ALIAS (no_aggregate_address, + no_aggregate_address_as_set_cmd, + "no aggregate-address A.B.C.D/M as-set", + NO_STR + "Configure BGP aggregate entries\n" + "Aggregate prefix\n" + "Generate AS set path information\n") + +ALIAS (no_aggregate_address, + no_aggregate_address_as_set_summary_cmd, + "no aggregate-address A.B.C.D/M as-set summary-only", + NO_STR + "Configure BGP aggregate entries\n" + "Aggregate prefix\n" + "Generate AS set path information\n" + "Filter more specific routes from updates\n") + +ALIAS (no_aggregate_address, + no_aggregate_address_summary_as_set_cmd, + "no aggregate-address A.B.C.D/M summary-only as-set", + NO_STR + "Configure BGP aggregate entries\n" + "Aggregate prefix\n" + "Filter more specific routes from updates\n" + "Generate AS set path information\n") + +DEFUN (no_aggregate_address_mask, + no_aggregate_address_mask_cmd, + "no aggregate-address A.B.C.D A.B.C.D", + NO_STR + "Configure BGP aggregate entries\n" + "Aggregate address\n" + "Aggregate mask\n") +{ + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str); + + if (! ret) + { + vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_aggregate_unset (vty, prefix_str, AFI_IP, bgp_node_safi (vty)); +} + +ALIAS (no_aggregate_address_mask, + no_aggregate_address_mask_summary_only_cmd, + "no aggregate-address A.B.C.D A.B.C.D summary-only", + NO_STR + "Configure BGP aggregate entries\n" + "Aggregate address\n" + "Aggregate mask\n" + "Filter more specific routes from updates\n") + +ALIAS (no_aggregate_address_mask, + no_aggregate_address_mask_as_set_cmd, + "no aggregate-address A.B.C.D A.B.C.D as-set", + NO_STR + "Configure BGP aggregate entries\n" + "Aggregate address\n" + "Aggregate mask\n" + "Generate AS set path information\n") + +ALIAS (no_aggregate_address_mask, + no_aggregate_address_mask_as_set_summary_cmd, + "no aggregate-address A.B.C.D A.B.C.D as-set summary-only", + NO_STR + "Configure BGP aggregate entries\n" + "Aggregate address\n" + "Aggregate mask\n" + "Generate AS set path information\n" + "Filter more specific routes from updates\n") + +ALIAS (no_aggregate_address_mask, + no_aggregate_address_mask_summary_as_set_cmd, + "no aggregate-address A.B.C.D A.B.C.D summary-only as-set", + NO_STR + "Configure BGP aggregate entries\n" + "Aggregate address\n" + "Aggregate mask\n" + "Filter more specific routes from updates\n" + "Generate AS set path information\n") + +#ifdef HAVE_IPV6 +DEFUN (ipv6_aggregate_address, + ipv6_aggregate_address_cmd, + "aggregate-address X:X::X:X/M", + "Configure BGP aggregate entries\n" + "Aggregate prefix\n") +{ + return bgp_aggregate_set (vty, argv[0], AFI_IP6, SAFI_UNICAST, 0, 0); +} + +DEFUN (ipv6_aggregate_address_summary_only, + ipv6_aggregate_address_summary_only_cmd, + "aggregate-address X:X::X:X/M summary-only", + "Configure BGP aggregate entries\n" + "Aggregate prefix\n" + "Filter more specific routes from updates\n") +{ + return bgp_aggregate_set (vty, argv[0], AFI_IP6, SAFI_UNICAST, + AGGREGATE_SUMMARY_ONLY, 0); +} + +DEFUN (no_ipv6_aggregate_address, + no_ipv6_aggregate_address_cmd, + "no aggregate-address X:X::X:X/M", + NO_STR + "Configure BGP aggregate entries\n" + "Aggregate prefix\n") +{ + return bgp_aggregate_unset (vty, argv[0], AFI_IP6, SAFI_UNICAST); +} + +DEFUN (no_ipv6_aggregate_address_summary_only, + no_ipv6_aggregate_address_summary_only_cmd, + "no aggregate-address X:X::X:X/M summary-only", + NO_STR + "Configure BGP aggregate entries\n" + "Aggregate prefix\n" + "Filter more specific routes from updates\n") +{ + return bgp_aggregate_unset (vty, argv[0], AFI_IP6, SAFI_UNICAST); +} + +ALIAS (ipv6_aggregate_address, + old_ipv6_aggregate_address_cmd, + "ipv6 bgp aggregate-address X:X::X:X/M", + IPV6_STR + BGP_STR + "Configure BGP aggregate entries\n" + "Aggregate prefix\n") + +ALIAS (ipv6_aggregate_address_summary_only, + old_ipv6_aggregate_address_summary_only_cmd, + "ipv6 bgp aggregate-address X:X::X:X/M summary-only", + IPV6_STR + BGP_STR + "Configure BGP aggregate entries\n" + "Aggregate prefix\n" + "Filter more specific routes from updates\n") + +ALIAS (no_ipv6_aggregate_address, + old_no_ipv6_aggregate_address_cmd, + "no ipv6 bgp aggregate-address X:X::X:X/M", + NO_STR + IPV6_STR + BGP_STR + "Configure BGP aggregate entries\n" + "Aggregate prefix\n") + +ALIAS (no_ipv6_aggregate_address_summary_only, + old_no_ipv6_aggregate_address_summary_only_cmd, + "no ipv6 bgp aggregate-address X:X::X:X/M summary-only", + NO_STR + IPV6_STR + BGP_STR + "Configure BGP aggregate entries\n" + "Aggregate prefix\n" + "Filter more specific routes from updates\n") +#endif /* HAVE_IPV6 */ + +/* Redistribute route treatment. */ +void +bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, + u_int32_t metric, u_char type) +{ + struct bgp *bgp; + struct listnode *nn; + struct bgp_info *new; + struct bgp_info *bi; + struct bgp_info info; + struct bgp_node *bn; + struct attr attr; + struct attr attr_new; + struct attr *new_attr; + afi_t afi; + int ret; + + /* Make default attribute. */ + bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE); + if (nexthop) + attr.nexthop = *nexthop; + + attr.med = metric; + attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); + + LIST_LOOP (bm->bgp, bgp, nn) + { + afi = family2afi (p->family); + + if (bgp->redist[afi][type]) + { + /* Copy attribute for modification. */ + attr_new = attr; + + if (bgp->redist_metric_flag[afi][type]) + attr_new.med = bgp->redist_metric[afi][type]; + + /* Apply route-map. */ + if (bgp->rmap[afi][type].map) + { + info.peer = bgp->peer_self; + info.attr = &attr_new; + + ret = route_map_apply (bgp->rmap[afi][type].map, p, RMAP_BGP, + &info); + if (ret == RMAP_DENYMATCH) + { + /* Free uninterned attribute. */ + bgp_attr_flush (&attr_new); + + /* Unintern original. */ + aspath_unintern (attr.aspath); + bgp_redistribute_delete (p, type); + return; + } + } + + bn = bgp_afi_node_get (bgp, afi, SAFI_UNICAST, p, NULL); + new_attr = bgp_attr_intern (&attr_new); + + for (bi = bn->info; bi; bi = bi->next) + if (bi->peer == bgp->peer_self + && bi->sub_type == BGP_ROUTE_REDISTRIBUTE) + break; + + if (bi) + { + if (attrhash_cmp (bi->attr, new_attr)) + { + bgp_attr_unintern (new_attr); + aspath_unintern (attr.aspath); + bgp_unlock_node (bn); + return; + } + else + { + /* The attribute is changed. */ + SET_FLAG (bi->flags, BGP_INFO_ATTR_CHANGED); + + /* Rewrite BGP route information. */ + bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST); + bgp_attr_unintern (bi->attr); + bi->attr = new_attr; + bi->uptime = time (NULL); + + /* Process change. */ + bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST); + bgp_process (bgp, bn, afi, SAFI_UNICAST); + bgp_unlock_node (bn); + aspath_unintern (attr.aspath); + return; + } + } + + new = bgp_info_new (); + new->type = type; + new->sub_type = BGP_ROUTE_REDISTRIBUTE; + new->peer = bgp->peer_self; + SET_FLAG (new->flags, BGP_INFO_VALID); + new->attr = new_attr; + new->uptime = time (NULL); + + bgp_aggregate_increment (bgp, p, new, afi, SAFI_UNICAST); + bgp_info_add (bn, new); + bgp_process (bgp, bn, afi, SAFI_UNICAST); + } + } + + /* Unintern original. */ + aspath_unintern (attr.aspath); +} + +void +bgp_redistribute_delete (struct prefix *p, u_char type) +{ + struct bgp *bgp; + struct listnode *nn; + afi_t afi; + struct bgp_node *rn; + struct bgp_info *ri; + + LIST_LOOP (bm->bgp, bgp, nn) + { + afi = family2afi (p->family); + + if (bgp->redist[afi][type]) + { + rn = bgp_afi_node_get (bgp, afi, SAFI_UNICAST, p, NULL); + + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self + && ri->type == type) + break; + + if (ri) + { + bgp_aggregate_decrement (bgp, p, ri, afi, SAFI_UNICAST); + UNSET_FLAG (ri->flags, BGP_INFO_VALID); + bgp_process (bgp, rn, afi, SAFI_UNICAST); + bgp_info_delete (rn, ri); + bgp_info_free (ri); + bgp_unlock_node (rn); + } + bgp_unlock_node (rn); + } + } +} + +/* Withdraw specified route type's route. */ +void +bgp_redistribute_withdraw (struct bgp *bgp, afi_t afi, int type) +{ + struct bgp_node *rn; + struct bgp_info *ri; + struct bgp_table *table; + + table = bgp->rib[afi][SAFI_UNICAST]; + + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + { + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self + && ri->type == type) + break; + + if (ri) + { + bgp_aggregate_decrement (bgp, &rn->p, ri, afi, SAFI_UNICAST); + UNSET_FLAG (ri->flags, BGP_INFO_VALID); + bgp_process (bgp, rn, afi, SAFI_UNICAST); + bgp_info_delete (rn, ri); + bgp_info_free (ri); + bgp_unlock_node (rn); + } + } +} + +/* Static function to display route. */ +void +route_vty_out_route (struct prefix *p, struct vty *vty) +{ + int len; + u_int32_t destination; + char buf[BUFSIZ]; + + if (p->family == AF_INET) + { + len = vty_out (vty, "%s", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ)); + destination = ntohl (p->u.prefix4.s_addr); + + if ((IN_CLASSC (destination) && p->prefixlen == 24) + || (IN_CLASSB (destination) && p->prefixlen == 16) + || (IN_CLASSA (destination) && p->prefixlen == 8) + || p->u.prefix4.s_addr == 0) + { + /* When mask is natural, mask is not displayed. */ + } + else + len += vty_out (vty, "/%d", p->prefixlen); + } + else + len = vty_out (vty, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), + p->prefixlen); + + len = 17 - len; + if (len < 1) + vty_out (vty, "%s%*s", VTY_NEWLINE, 20, " "); + else + vty_out (vty, "%*s", len, " "); +} + +/* Calculate line number of output data. */ +int +vty_calc_line (struct vty *vty, unsigned long length) +{ + return vty->width ? (((vty->obuf->length - length) / vty->width) + 1) : 1; +} + +enum bgp_display_type +{ + normal_list, +}; + +/* called from terminal list command */ +int +route_vty_out (struct vty *vty, struct prefix *p, + struct bgp_info *binfo, int display, safi_t safi) +{ + struct attr *attr; + unsigned long length = 0; + + length = vty->obuf->length; + + /* Route status display. */ + if (binfo->suppress) + vty_out (vty, "s"); + else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) + vty_out (vty, "*"); + else + vty_out (vty, " "); + + /* Selected */ + if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) + vty_out (vty, "h"); + else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) + vty_out (vty, "d"); + else if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) + vty_out (vty, ">"); + else + vty_out (vty, " "); + + /* Internal route. */ + if ((binfo->peer->as) && (binfo->peer->as == binfo->peer->local_as)) + vty_out (vty, "i"); + else + vty_out (vty, " "); + + /* print prefix and mask */ + if (! display) + route_vty_out_route (p, vty); + else + vty_out (vty, "%*s", 17, " "); + + /* Print attribute */ + attr = binfo->attr; + if (attr) + { + if (p->family == AF_INET) + { + if (safi == SAFI_MPLS_VPN) + vty_out (vty, "%-16s", inet_ntoa (attr->mp_nexthop_global_in)); + else + vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); + } +#ifdef HAVE_IPV6 + else if (p->family == AF_INET6) + { + int len; + char buf[BUFSIZ]; + + len = vty_out (vty, "%s", + inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ)); + len = 16 - len; + if (len < 1) + vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " "); + else + vty_out (vty, "%*s", len, " "); + } +#endif /* HAVE_IPV6 */ + + if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) + vty_out (vty, "%10d", attr->med); + else + vty_out (vty, " "); + + if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) + vty_out (vty, "%7d", attr->local_pref); + else + vty_out (vty, " "); + + vty_out (vty, "%7u ",attr->weight); + + /* Print aspath */ + if (attr->aspath) + aspath_print_vty (vty, attr->aspath); + + /* Print origin */ + if (strlen (attr->aspath->str) == 0) + vty_out (vty, "%s", bgp_origin_str[attr->origin]); + else + vty_out (vty, " %s", bgp_origin_str[attr->origin]); + } + vty_out (vty, "%s", VTY_NEWLINE); + + return vty_calc_line (vty, length); +} + +/* called from terminal list command */ +void +route_vty_out_tmp (struct vty *vty, struct prefix *p, + struct attr *attr, safi_t safi) +{ + /* Route status display. */ + vty_out (vty, "*"); + vty_out (vty, ">"); + vty_out (vty, " "); + + /* print prefix and mask */ + route_vty_out_route (p, vty); + + /* Print attribute */ + if (attr) + { + if (p->family == AF_INET) + { + if (safi == SAFI_MPLS_VPN) + vty_out (vty, "%-16s", inet_ntoa (attr->mp_nexthop_global_in)); + else + vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); + } +#ifdef HAVE_IPV6 + else if (p->family == AF_INET6) + { + int len; + char buf[BUFSIZ]; + + len = vty_out (vty, "%s", + inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ)); + len = 16 - len; + if (len < 1) + vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " "); + else + vty_out (vty, "%*s", len, " "); + } +#endif /* HAVE_IPV6 */ + + if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) + vty_out (vty, "%10d", attr->med); + else + vty_out (vty, " "); + + if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) + vty_out (vty, "%7d", attr->local_pref); + else + vty_out (vty, " "); + + vty_out (vty, "%7d ",attr->weight); + + /* Print aspath */ + if (attr->aspath) + aspath_print_vty (vty, attr->aspath); + + /* Print origin */ + if (strlen (attr->aspath->str) == 0) + vty_out (vty, "%s", bgp_origin_str[attr->origin]); + else + vty_out (vty, " %s", bgp_origin_str[attr->origin]); + } + + vty_out (vty, "%s", VTY_NEWLINE); +} + +int +route_vty_out_tag (struct vty *vty, struct prefix *p, + struct bgp_info *binfo, int display, safi_t safi) +{ + struct attr *attr; + unsigned long length = 0; + u_int32_t label = 0; + + length = vty->obuf->length; + + /* Route status display. */ + if (binfo->suppress) + vty_out (vty, "s"); + else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) + vty_out (vty, "*"); + else + vty_out (vty, " "); + + /* Selected */ + if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) + vty_out (vty, "h"); + else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) + vty_out (vty, "d"); + else if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) + vty_out (vty, ">"); + else + vty_out (vty, " "); + + /* Internal route. */ + if ((binfo->peer->as) && (binfo->peer->as == binfo->peer->local_as)) + vty_out (vty, "i"); + else + vty_out (vty, " "); + + /* print prefix and mask */ + if (! display) + route_vty_out_route (p, vty); + else + vty_out (vty, "%*s", 17, " "); + + /* Print attribute */ + attr = binfo->attr; + if (attr) + { + if (p->family == AF_INET) + { + if (safi == SAFI_MPLS_VPN) + vty_out (vty, "%-16s", inet_ntoa (attr->mp_nexthop_global_in)); + else + vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); + } +#ifdef HAVE_IPV6 + else if (p->family == AF_INET6) + { + char buf[BUFSIZ]; + char buf1[BUFSIZ]; + if (attr->mp_nexthop_len == 16) + vty_out (vty, "%s", + inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ)); + else if (attr->mp_nexthop_len == 32) + vty_out (vty, "%s(%s)", + inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ), + inet_ntop (AF_INET6, &attr->mp_nexthop_local, buf1, BUFSIZ)); + + } +#endif /* HAVE_IPV6 */ + } + + label = decode_label (binfo->tag); + + vty_out (vty, "notag/%d", label); + + vty_out (vty, "%s", VTY_NEWLINE); + + return vty_calc_line (vty, length); +} + +/* dampening route */ +int +damp_route_vty_out (struct vty *vty, struct prefix *p, + struct bgp_info *binfo, int display, safi_t safi) +{ + struct attr *attr; + unsigned long length = 0; + int len; + + length = vty->obuf->length; + + /* Route status display. */ + if (binfo->suppress) + vty_out (vty, "s"); + else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) + vty_out (vty, "*"); + else + vty_out (vty, " "); + + /* Selected */ + if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) + vty_out (vty, "h"); + else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) + vty_out (vty, "d"); + else if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) + vty_out (vty, ">"); + else + vty_out (vty, " "); + + vty_out (vty, " "); + + /* print prefix and mask */ + if (! display) + route_vty_out_route (p, vty); + else + vty_out (vty, "%*s", 17, " "); + + len = vty_out (vty, "%s", binfo->peer->host); + len = 17 - len; + if (len < 1) + vty_out (vty, "%s%*s", VTY_NEWLINE, 34, " "); + else + vty_out (vty, "%*s", len, " "); + + vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo)); + + /* Print attribute */ + attr = binfo->attr; + if (attr) + { + /* Print aspath */ + if (attr->aspath) + aspath_print_vty (vty, attr->aspath); + + /* Print origin */ + if (strlen (attr->aspath->str) == 0) + vty_out (vty, "%s", bgp_origin_str[attr->origin]); + else + vty_out (vty, " %s", bgp_origin_str[attr->origin]); + } + vty_out (vty, "%s", VTY_NEWLINE); + + return vty_calc_line (vty, length); +} + +#define BGP_UPTIME_LEN 25 + +/* flap route */ +int +flap_route_vty_out (struct vty *vty, struct prefix *p, + struct bgp_info *binfo, int display, safi_t safi) +{ + struct attr *attr; + struct bgp_damp_info *bdi; + unsigned long length = 0; + char timebuf[BGP_UPTIME_LEN]; + int len; + + length = vty->obuf->length; + bdi = binfo->damp_info; + + /* Route status display. */ + if (binfo->suppress) + vty_out (vty, "s"); + else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) + vty_out (vty, "*"); + else + vty_out (vty, " "); + + /* Selected */ + if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) + vty_out (vty, "h"); + else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) + vty_out (vty, "d"); + else if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) + vty_out (vty, ">"); + else + vty_out (vty, " "); + + vty_out (vty, " "); + + /* print prefix and mask */ + if (! display) + route_vty_out_route (p, vty); + else + vty_out (vty, "%*s", 17, " "); + + len = vty_out (vty, "%s", binfo->peer->host); + len = 16 - len; + if (len < 1) + vty_out (vty, "%s%*s", VTY_NEWLINE, 33, " "); + else + vty_out (vty, "%*s", len, " "); + + len = vty_out (vty, "%d", bdi->flap); + len = 5 - len; + if (len < 1) + vty_out (vty, " "); + else + vty_out (vty, "%*s ", len, " "); + + vty_out (vty, "%s ", peer_uptime (bdi->start_time, + timebuf, BGP_UPTIME_LEN)); + + if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED) + && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) + vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo)); + else + vty_out (vty, "%*s ", 8, " "); + + /* Print attribute */ + attr = binfo->attr; + if (attr) + { + /* Print aspath */ + if (attr->aspath) + aspath_print_vty (vty, attr->aspath); + + /* Print origin */ + if (strlen (attr->aspath->str) == 0) + vty_out (vty, "%s", bgp_origin_str[attr->origin]); + else + vty_out (vty, " %s", bgp_origin_str[attr->origin]); + } + vty_out (vty, "%s", VTY_NEWLINE); + + return vty_calc_line (vty, length); +} + +void +route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, + struct bgp_info *binfo, afi_t afi, safi_t safi) +{ + char buf[INET6_ADDRSTRLEN]; + char buf1[BUFSIZ]; + struct attr *attr; + int sockunion_vty_out (struct vty *, union sockunion *); + + attr = binfo->attr; + + if (attr) + { + /* Line1 display AS-path, Aggregator */ + if (attr->aspath) + { + vty_out (vty, " "); + if (attr->aspath->length == 0) + vty_out (vty, "Local"); + else + aspath_print_vty (vty, attr->aspath); + } + + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR) + || CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT) + || CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) + || CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY) + || CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) + { + vty_out (vty, ","); + + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) + vty_out (vty, " (aggregated by %d %s)", attr->aggregator_as, + inet_ntoa (attr->aggregator_addr)); + if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) + vty_out (vty, " (Received from a RR-client)"); + if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) + vty_out (vty, " (Received from a RS-client)"); + if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) + vty_out (vty, " (history entry)"); + else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) + vty_out (vty, " (suppressed due to dampening)"); + } + vty_out (vty, "%s", VTY_NEWLINE); + + /* Line2 display Next-hop, Neighbor, Router-id */ + if (p->family == AF_INET) + { + vty_out (vty, " %s", safi == SAFI_MPLS_VPN ? + inet_ntoa (attr->mp_nexthop_global_in) : + inet_ntoa (attr->nexthop)); + } +#ifdef HAVE_IPV6 + else + { + vty_out (vty, " %s", + inet_ntop (AF_INET6, &attr->mp_nexthop_global, + buf, INET6_ADDRSTRLEN)); + } +#endif /* HAVE_IPV6 */ + + if (binfo->peer == bgp->peer_self) + { + vty_out (vty, " from %s ", + p->family == AF_INET ? "0.0.0.0" : "::"); + vty_out (vty, "(%s)", inet_ntoa(bgp->router_id)); + } + else + { + if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID)) + vty_out (vty, " (inaccessible)"); + else if (binfo->igpmetric) + vty_out (vty, " (metric %d)", binfo->igpmetric); + vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN)); + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) + vty_out (vty, " (%s)", inet_ntoa (attr->originator_id)); + else + vty_out (vty, " (%s)", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ)); + } + vty_out (vty, "%s", VTY_NEWLINE); + +#ifdef HAVE_IPV6 + /* display nexthop local */ + if (attr->mp_nexthop_len == 32) + { + vty_out (vty, " (%s)%s", + inet_ntop (AF_INET6, &attr->mp_nexthop_local, + buf, INET6_ADDRSTRLEN), + VTY_NEWLINE); + } +#endif /* HAVE_IPV6 */ + + /* Line 3 display Origin, Med, Locpref, Weight, valid, Int/Ext/Local, Atomic, best */ + vty_out (vty, " Origin %s", bgp_origin_long_str[attr->origin]); + + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) + vty_out (vty, ", metric %d", attr->med); + + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) + vty_out (vty, ", localpref %d", attr->local_pref); + else + vty_out (vty, ", localpref %d", bgp->default_local_pref); + + if (attr->weight != 0) + vty_out (vty, ", weight %d", attr->weight); + + if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) + vty_out (vty, ", valid"); + + if (binfo->peer != bgp->peer_self) + { + if (binfo->peer->as == binfo->peer->local_as) + vty_out (vty, ", internal"); + else + vty_out (vty, ", %s", + (bgp_confederation_peers_check(bgp, binfo->peer->as) ? "confed-external" : "external")); + } + else if (binfo->sub_type == BGP_ROUTE_AGGREGATE) + vty_out (vty, ", aggregated, local"); + else if (binfo->type != ZEBRA_ROUTE_BGP) + vty_out (vty, ", sourced"); + else + vty_out (vty, ", sourced, local"); + + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) + vty_out (vty, ", atomic-aggregate"); + + if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) + vty_out (vty, ", best"); + + vty_out (vty, "%s", VTY_NEWLINE); + + /* Line 4 display Community */ + if (attr->community) + vty_out (vty, " Community: %s%s", attr->community->str, + VTY_NEWLINE); + + /* Line 5 display Extended-community */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) + vty_out (vty, " Extended Community: %s%s", attr->ecommunity->str, + VTY_NEWLINE); + + /* Line 6 display Originator, Cluster-id */ + if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) || + (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) + { + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) + vty_out (vty, " Originator: %s", inet_ntoa (attr->originator_id)); + + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) + { + int i; + vty_out (vty, ", Cluster list: "); + for (i = 0; i < attr->cluster->length / 4; i++) + vty_out (vty, "%s ", inet_ntoa (attr->cluster->list[i])); + } + vty_out (vty, "%s", VTY_NEWLINE); + } + + if (binfo->damp_info) + bgp_damp_info_vty (vty, binfo); + + /* Line 7 display Uptime */ + vty_out (vty, " Last update: %s", ctime (&binfo->uptime)); + } + vty_out (vty, "%s", VTY_NEWLINE); +} + +#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path%s" +#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path%s" +#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path%s" + +enum bgp_show_type +{ + bgp_show_type_normal, + bgp_show_type_regexp, + bgp_show_type_prefix_list, + bgp_show_type_filter_list, + bgp_show_type_route_map, + bgp_show_type_neighbor, + bgp_show_type_cidr_only, + bgp_show_type_prefix_longer, + bgp_show_type_community_all, + bgp_show_type_community, + bgp_show_type_community_exact, + bgp_show_type_community_list, + bgp_show_type_community_list_exact, + bgp_show_type_flap_statistics, + bgp_show_type_flap_address, + bgp_show_type_flap_prefix, + bgp_show_type_flap_cidr_only, + bgp_show_type_flap_regexp, + bgp_show_type_flap_filter_list, + bgp_show_type_flap_prefix_list, + bgp_show_type_flap_prefix_longer, + bgp_show_type_flap_route_map, + bgp_show_type_flap_neighbor, + bgp_show_type_dampend_paths, + bgp_show_type_damp_neighbor +}; + +int +bgp_show_callback (struct vty *vty, int unlock) +{ + struct bgp_node *rn; + struct bgp_info *ri; + int count; + int limit; + int display; + + rn = vty->output_rn; + count = 0; + limit = ((vty->lines == 0) + ? 10 : (vty->lines > 0 + ? vty->lines : vty->height - 2)); + limit = limit > 0 ? limit : 2; + + /* Quit of display. */ + if (unlock && rn) + { + bgp_unlock_node (rn); + if (vty->output_clean) + (*vty->output_clean) (vty); + vty->output_rn = NULL; + vty->output_func = NULL; + vty->output_clean = NULL; + vty->output_arg = NULL; + return 0; + } + + for (; rn; rn = bgp_route_next (rn)) + if (rn->info != NULL) + { + display = 0; + + for (ri = rn->info; ri; ri = ri->next) + { + if (vty->output_type == bgp_show_type_flap_statistics + || vty->output_type == bgp_show_type_flap_address + || vty->output_type == bgp_show_type_flap_prefix + || vty->output_type == bgp_show_type_flap_cidr_only + || vty->output_type == bgp_show_type_flap_regexp + || vty->output_type == bgp_show_type_flap_filter_list + || vty->output_type == bgp_show_type_flap_prefix_list + || vty->output_type == bgp_show_type_flap_prefix_longer + || vty->output_type == bgp_show_type_flap_route_map + || vty->output_type == bgp_show_type_flap_neighbor + || vty->output_type == bgp_show_type_dampend_paths + || vty->output_type == bgp_show_type_damp_neighbor) + { + if (! ri->damp_info) + continue; + } + if (vty->output_type == bgp_show_type_regexp + || vty->output_type == bgp_show_type_flap_regexp) + { + regex_t *regex = vty->output_arg; + + if (bgp_regexec (regex, ri->attr->aspath) == REG_NOMATCH) + continue; + } + if (vty->output_type == bgp_show_type_prefix_list + || vty->output_type == bgp_show_type_flap_prefix_list) + { + struct prefix_list *plist = vty->output_arg; + + if (prefix_list_apply (plist, &rn->p) != PREFIX_PERMIT) + continue; + } + if (vty->output_type == bgp_show_type_filter_list + || vty->output_type == bgp_show_type_flap_filter_list) + { + struct as_list *as_list = vty->output_arg; + + if (as_list_apply (as_list, ri->attr->aspath) != AS_FILTER_PERMIT) + continue; + } + if (vty->output_type == bgp_show_type_route_map + || vty->output_type == bgp_show_type_flap_route_map) + { + struct route_map *rmap = vty->output_arg; + struct bgp_info binfo; + struct attr dummy_attr; + int ret; + + dummy_attr = *ri->attr; + binfo.peer = ri->peer; + binfo.attr = &dummy_attr; + + ret = route_map_apply (rmap, &rn->p, RMAP_BGP, &binfo); + + if (ret == RMAP_DENYMATCH) + continue; + } + if (vty->output_type == bgp_show_type_neighbor + || vty->output_type == bgp_show_type_flap_neighbor + || vty->output_type == bgp_show_type_damp_neighbor) + { + union sockunion *su = vty->output_arg; + + if (ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su)) + continue; + } + if (vty->output_type == bgp_show_type_cidr_only + || vty->output_type == bgp_show_type_flap_cidr_only) + { + u_int32_t destination; + + destination = ntohl (rn->p.u.prefix4.s_addr); + if (IN_CLASSC (destination) && rn->p.prefixlen == 24) + continue; + if (IN_CLASSB (destination) && rn->p.prefixlen == 16) + continue; + if (IN_CLASSA (destination) && rn->p.prefixlen == 8) + continue; + } + if (vty->output_type == bgp_show_type_prefix_longer + || vty->output_type == bgp_show_type_flap_prefix_longer) + { + struct prefix *p = vty->output_arg; + + if (! prefix_match (p, &rn->p)) + continue; + } + if (vty->output_type == bgp_show_type_community_all) + { + if (! ri->attr->community) + continue; + } + if (vty->output_type == bgp_show_type_community) + { + struct community *com = vty->output_arg; + + if (! ri->attr->community || + ! community_match (ri->attr->community, com)) + continue; + } + if (vty->output_type == bgp_show_type_community_exact) + { + struct community *com = vty->output_arg; + + if (! ri->attr->community || + ! community_cmp (ri->attr->community, com)) + continue; + } + if (vty->output_type == bgp_show_type_community_list) + { + struct community_list *list = vty->output_arg; + + if (! community_list_match (ri->attr->community, list)) + continue; + } + if (vty->output_type == bgp_show_type_community_list_exact) + { + struct community_list *list = vty->output_arg; + + if (! community_list_exact_match (ri->attr->community, list)) + continue; + } + if (vty->output_type == bgp_show_type_flap_address + || vty->output_type == bgp_show_type_flap_prefix) + { + struct prefix *p = vty->output_arg; + + if (! prefix_match (&rn->p, p)) + continue; + + if (vty->output_type == bgp_show_type_flap_prefix) + if (p->prefixlen != rn->p.prefixlen) + continue; + } + if (vty->output_type == bgp_show_type_dampend_paths + || vty->output_type == bgp_show_type_damp_neighbor) + { + if (! CHECK_FLAG (ri->flags, BGP_INFO_DAMPED) + || CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) + continue; + } + + if (vty->output_type == bgp_show_type_dampend_paths + || vty->output_type == bgp_show_type_damp_neighbor) + count += damp_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST); + else if (vty->output_type == bgp_show_type_flap_statistics + || vty->output_type == bgp_show_type_flap_address + || vty->output_type == bgp_show_type_flap_prefix + || vty->output_type == bgp_show_type_flap_cidr_only + || vty->output_type == bgp_show_type_flap_regexp + || vty->output_type == bgp_show_type_flap_filter_list + || vty->output_type == bgp_show_type_flap_prefix_list + || vty->output_type == bgp_show_type_flap_prefix_longer + || vty->output_type == bgp_show_type_flap_route_map + || vty->output_type == bgp_show_type_flap_neighbor) + count += flap_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST); + else + count += route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST); + display++; + } + + if (display) + vty->output_count++; + + /* Remember current pointer then suspend output. */ + if (count >= limit) + { + vty->status = VTY_CONTINUE; + vty->output_rn = bgp_route_next (rn);; + vty->output_func = bgp_show_callback; + return 0; + } + } + + /* Total line display. */ + if (vty->output_count) + vty_out (vty, "%sTotal number of prefixes %ld%s", + VTY_NEWLINE, vty->output_count, VTY_NEWLINE); + + if (vty->output_clean) + (*vty->output_clean) (vty); + + vty->status = VTY_CONTINUE; + vty->output_rn = NULL; + vty->output_func = NULL; + vty->output_clean = NULL; + vty->output_arg = NULL; + + return 0; +} + +int +bgp_show (struct vty *vty, char *view_name, afi_t afi, safi_t safi, + enum bgp_show_type type) +{ + struct bgp *bgp; + struct bgp_info *ri; + struct bgp_node *rn; + struct bgp_table *table; + int header = 1; + int count; + int limit; + int display; + + limit = ((vty->lines == 0) + ? 10 : (vty->lines > 0 + ? vty->lines : vty->height - 2)); + limit = limit > 0 ? limit : 2; + + /* BGP structure lookup. */ + if (view_name) + { + bgp = bgp_lookup_by_name (view_name); + if (bgp == NULL) + { + vty_out (vty, "Can't find BGP view %s%s", view_name, VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + bgp = bgp_get_default (); + if (bgp == NULL) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + + count = 0; + + /* This is first entry point, so reset total line. */ + vty->output_count = 0; + vty->output_type = type; + + table = bgp->rib[afi][safi]; + + /* Start processing of routes. */ + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + if (rn->info != NULL) + { + display = 0; + + for (ri = rn->info; ri; ri = ri->next) + { + if (vty->output_type == bgp_show_type_flap_statistics + || type == bgp_show_type_flap_address + || type == bgp_show_type_flap_prefix + || type == bgp_show_type_flap_cidr_only + || type == bgp_show_type_flap_regexp + || type == bgp_show_type_flap_filter_list + || type == bgp_show_type_flap_prefix_list + || type == bgp_show_type_flap_prefix_longer + || type == bgp_show_type_flap_route_map + || type == bgp_show_type_flap_neighbor + || type == bgp_show_type_dampend_paths + || type == bgp_show_type_damp_neighbor) + { + if (! ri->damp_info) + continue; + } + if (type == bgp_show_type_regexp + || type == bgp_show_type_flap_regexp) + { + regex_t *regex = vty->output_arg; + + if (bgp_regexec (regex, ri->attr->aspath) == REG_NOMATCH) + continue; + } + if (type == bgp_show_type_prefix_list + || type == bgp_show_type_flap_prefix_list) + { + struct prefix_list *plist = vty->output_arg; + + if (prefix_list_apply (plist, &rn->p) != PREFIX_PERMIT) + continue; + } + if (type == bgp_show_type_filter_list + || type == bgp_show_type_flap_filter_list) + { + struct as_list *as_list = vty->output_arg; + + if (as_list_apply (as_list, ri->attr->aspath) != AS_FILTER_PERMIT) + continue; + } + if (type == bgp_show_type_route_map + || type == bgp_show_type_flap_route_map) + { + struct route_map *rmap = vty->output_arg; + struct bgp_info binfo; + struct attr dummy_attr; + int ret; + + dummy_attr = *ri->attr; + binfo.peer = ri->peer; + binfo.attr = &dummy_attr; + + ret = route_map_apply (rmap, &rn->p, RMAP_BGP, &binfo); + + if (ret == RMAP_DENYMATCH) + continue; + } + if (type == bgp_show_type_neighbor + || type == bgp_show_type_flap_neighbor + || type == bgp_show_type_damp_neighbor) + { + union sockunion *su = vty->output_arg; + + if (ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su)) + continue; + } + if (type == bgp_show_type_cidr_only + || type == bgp_show_type_flap_cidr_only) + { + u_int32_t destination; + + destination = ntohl (rn->p.u.prefix4.s_addr); + if (IN_CLASSC (destination) && rn->p.prefixlen == 24) + continue; + if (IN_CLASSB (destination) && rn->p.prefixlen == 16) + continue; + if (IN_CLASSA (destination) && rn->p.prefixlen == 8) + continue; + } + if (type == bgp_show_type_prefix_longer + || type == bgp_show_type_flap_prefix_longer) + { + struct prefix *p = vty->output_arg; + + if (! prefix_match (p, &rn->p)) + continue; + } + if (type == bgp_show_type_community_all) + { + if (! ri->attr->community) + continue; + } + if (type == bgp_show_type_community) + { + struct community *com = vty->output_arg; + + if (! ri->attr->community || + ! community_match (ri->attr->community, com)) + continue; + } + if (type == bgp_show_type_community_exact) + { + struct community *com = vty->output_arg; + + if (! ri->attr->community || + ! community_cmp (ri->attr->community, com)) + continue; + } + if (type == bgp_show_type_community_list) + { + struct community_list *list = vty->output_arg; + + if (! community_list_match (ri->attr->community, list)) + continue; + } + if (type == bgp_show_type_community_list_exact) + { + struct community_list *list = vty->output_arg; + + if (! community_list_exact_match (ri->attr->community, list)) + continue; + } + if (type == bgp_show_type_flap_address + || type == bgp_show_type_flap_prefix) + { + struct prefix *p = vty->output_arg; + + if (! prefix_match (&rn->p, p)) + continue; + + if (type == bgp_show_type_flap_prefix) + if (p->prefixlen != rn->p.prefixlen) + continue; + } + if (type == bgp_show_type_dampend_paths + || type == bgp_show_type_damp_neighbor) + { + if (! CHECK_FLAG (ri->flags, BGP_INFO_DAMPED) + || CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) + continue; + } + + if (header) + { + vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE); + vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s", VTY_NEWLINE); + vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s", VTY_NEWLINE, VTY_NEWLINE); + if (type == bgp_show_type_dampend_paths + || type == bgp_show_type_damp_neighbor) + vty_out (vty, BGP_SHOW_DAMP_HEADER, VTY_NEWLINE); + else if (type == bgp_show_type_flap_statistics + || type == bgp_show_type_flap_address + || type == bgp_show_type_flap_prefix + || type == bgp_show_type_flap_cidr_only + || type == bgp_show_type_flap_regexp + || type == bgp_show_type_flap_filter_list + || type == bgp_show_type_flap_prefix_list + || type == bgp_show_type_flap_prefix_longer + || type == bgp_show_type_flap_route_map + || type == bgp_show_type_flap_neighbor) + vty_out (vty, BGP_SHOW_FLAP_HEADER, VTY_NEWLINE); + else + vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE); + count += 5; + header = 0; + } + + if (type == bgp_show_type_dampend_paths + || type == bgp_show_type_damp_neighbor) + count += damp_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST); + else if (type == bgp_show_type_flap_statistics + || type == bgp_show_type_flap_address + || type == bgp_show_type_flap_prefix + || type == bgp_show_type_flap_cidr_only + || type == bgp_show_type_flap_regexp + || type == bgp_show_type_flap_filter_list + || type == bgp_show_type_flap_prefix_list + || type == bgp_show_type_flap_prefix_longer + || type == bgp_show_type_flap_route_map + || type == bgp_show_type_flap_neighbor) + count += flap_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST); + else + count += route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST); + display++; + } + if (display) + vty->output_count++; + + /* Remember current pointer then suspend output. */ + if (count >= limit && vty->type != VTY_SHELL_SERV) + { + vty->status = VTY_START; + vty->output_rn = bgp_route_next (rn); + vty->output_func = bgp_show_callback; + vty->output_type = type; + + return CMD_SUCCESS; + } + } + + /* No route is displayed */ + if (vty->output_count == 0) + { + if (type == bgp_show_type_normal) + vty_out (vty, "No BGP network exists%s", VTY_NEWLINE); + } + else + vty_out (vty, "%sTotal number of prefixes %ld%s", + VTY_NEWLINE, vty->output_count, VTY_NEWLINE); + + /* Clean up allocated resources. */ + if (vty->output_clean) + (*vty->output_clean) (vty); + + vty->status = VTY_START; + vty->output_rn = NULL; + vty->output_func = NULL; + vty->output_clean = NULL; + vty->output_arg = NULL; + + return CMD_SUCCESS; +} + +/* Header of detailed BGP route information */ +void +route_vty_out_detail_header (struct vty *vty, struct bgp *bgp, + struct bgp_node *rn, + struct prefix_rd *prd, afi_t afi, safi_t safi) +{ + struct bgp_info *ri; + struct prefix *p; + struct peer *peer; + struct listnode *nn; + char buf1[INET6_ADDRSTRLEN]; + char buf2[INET6_ADDRSTRLEN]; + int count = 0; + int best = 0; + int suppress = 0; + int no_export = 0; + int no_advertise = 0; + int local_as = 0; + int first = 0; + + p = &rn->p; + vty_out (vty, "BGP routing table entry for %s%s%s/%d%s", + (safi == SAFI_MPLS_VPN ? + prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""), + safi == SAFI_MPLS_VPN ? ":" : "", + inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN), + p->prefixlen, VTY_NEWLINE); + + for (ri = rn->info; ri; ri = ri->next) + { + count++; + if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) + { + best = count; + if (ri->suppress) + suppress = 1; + if (ri->attr->community != NULL) + { + if (community_include (ri->attr->community, COMMUNITY_NO_ADVERTISE)) + no_advertise = 1; + if (community_include (ri->attr->community, COMMUNITY_NO_EXPORT)) + no_export = 1; + if (community_include (ri->attr->community, COMMUNITY_LOCAL_AS)) + local_as = 1; + } + } + } + + vty_out (vty, "Paths: (%d available", count); + if (best) + { + vty_out (vty, ", best #%d", best); + if (safi == SAFI_UNICAST) + vty_out (vty, ", table Default-IP-Routing-Table"); + } + else + vty_out (vty, ", no best path"); + if (no_advertise) + vty_out (vty, ", not advertised to any peer"); + else if (no_export) + vty_out (vty, ", not advertised to EBGP peer"); + else if (local_as) + vty_out (vty, ", not advertised outside local AS"); + if (suppress) + vty_out (vty, ", Advertisements suppressed by an aggregate."); + vty_out (vty, ")%s", VTY_NEWLINE); + + /* advertised peer */ + LIST_LOOP (bgp->peer, peer, nn) + { + if (bgp_adj_out_lookup (peer, p, afi, safi, rn)) + { + if (! first) + vty_out (vty, " Advertised to non peer-group peers:%s ", VTY_NEWLINE); + vty_out (vty, " %s", sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN)); + first = 1; + } + } + if (! first) + vty_out (vty, " Not advertised to any peer"); + vty_out (vty, "%s", VTY_NEWLINE); +} + +/* Display specified route of BGP table. */ +int +bgp_show_route (struct vty *vty, char *view_name, char *ip_str, + afi_t afi, safi_t safi, struct prefix_rd *prd, + int prefix_check) +{ + int ret; + int header; + int display = 0; + struct prefix match; + struct bgp_node *rn; + struct bgp_node *rm; + struct bgp_info *ri; + struct bgp *bgp; + struct bgp_table *table; + + /* BGP structure lookup. */ + if (view_name) + { + bgp = bgp_lookup_by_name (view_name); + if (bgp == NULL) + { + vty_out (vty, "Can't find BGP view %s%s", view_name, VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + bgp = bgp_get_default (); + if (bgp == NULL) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + + /* Check IP address argument. */ + ret = str2prefix (ip_str, &match); + if (! ret) + { + vty_out (vty, "address is malformed%s", VTY_NEWLINE); + return CMD_WARNING; + } + + match.family = afi2family (afi); + + if (safi == SAFI_MPLS_VPN) + { + for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn)) + { + if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) + continue; + + if ((table = rn->info) != NULL) + { + header = 1; + + if ((rm = bgp_node_match (table, &match)) != NULL) + { + if (prefix_check && rm->p.prefixlen != match.prefixlen) + continue; + + for (ri = rm->info; ri; ri = ri->next) + { + if (header) + { + route_vty_out_detail_header (vty, bgp, rm, (struct prefix_rd *)&rn->p, + AFI_IP, SAFI_MPLS_VPN); + + header = 0; + } + display++; + route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, SAFI_MPLS_VPN); + } + } + } + } + } + else + { + header = 1; + + if ((rn = bgp_node_match (bgp->rib[afi][safi], &match)) != NULL) + { + if (! prefix_check || rn->p.prefixlen == match.prefixlen) + { + for (ri = rn->info; ri; ri = ri->next) + { + if (header) + { + route_vty_out_detail_header (vty, bgp, rn, NULL, afi, safi); + header = 0; + } + display++; + route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi); + } + } + } + } + + if (! display) + { + vty_out (vty, "%% Network not in table%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +/* BGP route print out function. */ +DEFUN (show_ip_bgp, + show_ip_bgp_cmd, + "show ip bgp", + SHOW_STR + IP_STR + BGP_STR) +{ + return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_normal); +} + +DEFUN (show_ip_bgp_ipv4, + show_ip_bgp_ipv4_cmd, + "show ip bgp ipv4 (unicast|multicast)", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, bgp_show_type_normal); + + return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_normal); +} + +DEFUN (show_ip_bgp_route, + show_ip_bgp_route_cmd, + "show ip bgp A.B.C.D", + SHOW_STR + IP_STR + BGP_STR + "Network in the BGP routing table to display\n") +{ + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 0); +} + +DEFUN (show_ip_bgp_ipv4_route, + show_ip_bgp_ipv4_route_cmd, + "show ip bgp ipv4 (unicast|multicast) A.B.C.D", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Network in the BGP routing table to display\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0); + + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0); +} + +DEFUN (show_ip_bgp_vpnv4_all_route, + show_ip_bgp_vpnv4_all_route_cmd, + "show ip bgp vpnv4 all A.B.C.D", + SHOW_STR + IP_STR + BGP_STR + "Display VPNv4 NLRI specific information\n" + "Display information about all VPNv4 NLRIs\n" + "Network in the BGP routing table to display\n") +{ + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 0); +} + +DEFUN (show_ip_bgp_vpnv4_rd_route, + show_ip_bgp_vpnv4_rd_route_cmd, + "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn A.B.C.D", + SHOW_STR + IP_STR + BGP_STR + "Display VPNv4 NLRI specific information\n" + "Display information for a route distinguisher\n" + "VPN Route Distinguisher\n" + "Network in the BGP routing table to display\n") +{ + int ret; + struct prefix_rd prd; + + ret = str2prefix_rd (argv[0], &prd); + if (! ret) + { + vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); + return CMD_WARNING; + } + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 0); +} + +DEFUN (show_ip_bgp_prefix, + show_ip_bgp_prefix_cmd, + "show ip bgp A.B.C.D/M", + SHOW_STR + IP_STR + BGP_STR + "IP prefix /, e.g., 35.0.0.0/8\n") +{ + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1); +} + +DEFUN (show_ip_bgp_ipv4_prefix, + show_ip_bgp_ipv4_prefix_cmd, + "show ip bgp ipv4 (unicast|multicast) A.B.C.D/M", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "IP prefix /, e.g., 35.0.0.0/8\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1); + + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1); +} + +DEFUN (show_ip_bgp_vpnv4_all_prefix, + show_ip_bgp_vpnv4_all_prefix_cmd, + "show ip bgp vpnv4 all A.B.C.D/M", + SHOW_STR + IP_STR + BGP_STR + "Display VPNv4 NLRI specific information\n" + "Display information about all VPNv4 NLRIs\n" + "IP prefix /, e.g., 35.0.0.0/8\n") +{ + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 1); +} + +DEFUN (show_ip_bgp_vpnv4_rd_prefix, + show_ip_bgp_vpnv4_rd_prefix_cmd, + "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn A.B.C.D/M", + SHOW_STR + IP_STR + BGP_STR + "Display VPNv4 NLRI specific information\n" + "Display information for a route distinguisher\n" + "VPN Route Distinguisher\n" + "IP prefix /, e.g., 35.0.0.0/8\n") +{ + int ret; + struct prefix_rd prd; + + ret = str2prefix_rd (argv[0], &prd); + if (! ret) + { + vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); + return CMD_WARNING; + } + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 1); +} + +DEFUN (show_ip_bgp_view, + show_ip_bgp_view_cmd, + "show ip bgp view WORD", + SHOW_STR + IP_STR + BGP_STR + "BGP view\n" + "BGP view name\n") +{ + return bgp_show (vty, argv[0], AFI_IP, SAFI_UNICAST, bgp_show_type_normal); +} + +DEFUN (show_ip_bgp_view_route, + show_ip_bgp_view_route_cmd, + "show ip bgp view WORD A.B.C.D", + SHOW_STR + IP_STR + BGP_STR + "BGP view\n" + "BGP view name\n" + "Network in the BGP routing table to display\n") +{ + return bgp_show_route (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, NULL, 0); +} + +DEFUN (show_ip_bgp_view_prefix, + show_ip_bgp_view_prefix_cmd, + "show ip bgp view WORD A.B.C.D/M", + SHOW_STR + IP_STR + BGP_STR + "BGP view\n" + "BGP view name\n" + "IP prefix /, e.g., 35.0.0.0/8\n") +{ + return bgp_show_route (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, NULL, 1); +} + +#ifdef HAVE_IPV6 +DEFUN (show_bgp, + show_bgp_cmd, + "show bgp", + SHOW_STR + BGP_STR) +{ + return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST, bgp_show_type_normal); +} + +ALIAS (show_bgp, + show_bgp_ipv6_cmd, + "show bgp ipv6", + SHOW_STR + BGP_STR + "Address family\n") + +/* old command */ +DEFUN (show_ipv6_bgp, + show_ipv6_bgp_cmd, + "show ipv6 bgp", + SHOW_STR + IP_STR + BGP_STR) +{ + return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST, bgp_show_type_normal); +} + +DEFUN (show_bgp_route, + show_bgp_route_cmd, + "show bgp X:X::X:X", + SHOW_STR + BGP_STR + "Network in the BGP routing table to display\n") +{ + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0); +} + +ALIAS (show_bgp_route, + show_bgp_ipv6_route_cmd, + "show bgp ipv6 X:X::X:X", + SHOW_STR + BGP_STR + "Address family\n" + "Network in the BGP routing table to display\n") + +/* old command */ +DEFUN (show_ipv6_bgp_route, + show_ipv6_bgp_route_cmd, + "show ipv6 bgp X:X::X:X", + SHOW_STR + IP_STR + BGP_STR + "Network in the BGP routing table to display\n") +{ + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0); +} + +DEFUN (show_bgp_prefix, + show_bgp_prefix_cmd, + "show bgp X:X::X:X/M", + SHOW_STR + BGP_STR + "IPv6 prefix /\n") +{ + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1); +} + +ALIAS (show_bgp_prefix, + show_bgp_ipv6_prefix_cmd, + "show bgp ipv6 X:X::X:X/M", + SHOW_STR + BGP_STR + "Address family\n" + "IPv6 prefix /\n") + +/* old command */ +DEFUN (show_ipv6_bgp_prefix, + show_ipv6_bgp_prefix_cmd, + "show ipv6 bgp X:X::X:X/M", + SHOW_STR + IP_STR + BGP_STR + "IPv6 prefix /, e.g., 3ffe::/16\n") +{ + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1); +} + +/* old command */ +DEFUN (show_ipv6_mbgp, + show_ipv6_mbgp_cmd, + "show ipv6 mbgp", + SHOW_STR + IP_STR + MBGP_STR) +{ + return bgp_show (vty, NULL, AFI_IP6, SAFI_MULTICAST, bgp_show_type_normal); +} + +/* old command */ +DEFUN (show_ipv6_mbgp_route, + show_ipv6_mbgp_route_cmd, + "show ipv6 mbgp X:X::X:X", + SHOW_STR + IP_STR + MBGP_STR + "Network in the MBGP routing table to display\n") +{ + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 0); +} + +/* old command */ +DEFUN (show_ipv6_mbgp_prefix, + show_ipv6_mbgp_prefix_cmd, + "show ipv6 mbgp X:X::X:X/M", + SHOW_STR + IP_STR + MBGP_STR + "IPv6 prefix /, e.g., 3ffe::/16\n") +{ + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 1); +} +#endif + +void +bgp_show_regexp_clean (struct vty *vty) +{ + bgp_regex_free (vty->output_arg); +} + +int +bgp_show_regexp (struct vty *vty, int argc, char **argv, afi_t afi, + safi_t safi, enum bgp_show_type type) +{ + int i; + struct buffer *b; + char *regstr; + int first; + regex_t *regex; + + first = 0; + b = buffer_new (1024); + for (i = 0; i < argc; i++) + { + if (first) + buffer_putc (b, ' '); + else + { + if ((strcmp (argv[i], "unicast") == 0) || (strcmp (argv[i], "multicast") == 0)) + continue; + first = 1; + } + + buffer_putstr (b, argv[i]); + } + buffer_putc (b, '\0'); + + regstr = buffer_getstr (b); + buffer_free (b); + + regex = bgp_regcomp (regstr); + if (! regex) + { + vty_out (vty, "Can't compile regexp %s%s", argv[0], + VTY_NEWLINE); + return CMD_WARNING; + } + + vty->output_arg = regex; + vty->output_clean = bgp_show_regexp_clean; + + return bgp_show (vty, NULL, afi, safi, type); +} + +DEFUN (show_ip_bgp_regexp, + show_ip_bgp_regexp_cmd, + "show ip bgp regexp .LINE", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the AS path regular expression\n" + "A regular-expression to match the BGP AS paths\n") +{ + return bgp_show_regexp (vty, argc, argv, AFI_IP, SAFI_UNICAST, + bgp_show_type_regexp); +} + +DEFUN (show_ip_bgp_flap_regexp, + show_ip_bgp_flap_regexp_cmd, + "show ip bgp flap-statistics regexp .LINE", + SHOW_STR + IP_STR + BGP_STR + "Display flap statistics of routes\n" + "Display routes matching the AS path regular expression\n" + "A regular-expression to match the BGP AS paths\n") +{ + return bgp_show_regexp (vty, argc, argv, AFI_IP, SAFI_UNICAST, + bgp_show_type_flap_regexp); +} + +DEFUN (show_ip_bgp_ipv4_regexp, + show_ip_bgp_ipv4_regexp_cmd, + "show ip bgp ipv4 (unicast|multicast) regexp .LINE", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the AS path regular expression\n" + "A regular-expression to match the BGP AS paths\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_regexp (vty, argc, argv, AFI_IP, SAFI_MULTICAST, + bgp_show_type_regexp); + + return bgp_show_regexp (vty, argc, argv, AFI_IP, SAFI_UNICAST, + bgp_show_type_regexp); +} + +#ifdef HAVE_IPV6 +DEFUN (show_bgp_regexp, + show_bgp_regexp_cmd, + "show bgp regexp .LINE", + SHOW_STR + BGP_STR + "Display routes matching the AS path regular expression\n" + "A regular-expression to match the BGP AS paths\n") +{ + return bgp_show_regexp (vty, argc, argv, AFI_IP6, SAFI_UNICAST, + bgp_show_type_regexp); +} + +ALIAS (show_bgp_regexp, + show_bgp_ipv6_regexp_cmd, + "show bgp ipv6 regexp .LINE", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes matching the AS path regular expression\n" + "A regular-expression to match the BGP AS paths\n") + +/* old command */ +DEFUN (show_ipv6_bgp_regexp, + show_ipv6_bgp_regexp_cmd, + "show ipv6 bgp regexp .LINE", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the AS path regular expression\n" + "A regular-expression to match the BGP AS paths\n") +{ + return bgp_show_regexp (vty, argc, argv, AFI_IP6, SAFI_UNICAST, + bgp_show_type_regexp); +} + +/* old command */ +DEFUN (show_ipv6_mbgp_regexp, + show_ipv6_mbgp_regexp_cmd, + "show ipv6 mbgp regexp .LINE", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the AS path regular expression\n" + "A regular-expression to match the MBGP AS paths\n") +{ + return bgp_show_regexp (vty, argc, argv, AFI_IP6, SAFI_MULTICAST, + bgp_show_type_regexp); +} +#endif /* HAVE_IPV6 */ + +int +bgp_show_prefix_list (struct vty *vty, char *prefix_list_str, afi_t afi, + safi_t safi, enum bgp_show_type type) +{ + struct prefix_list *plist; + + plist = prefix_list_lookup (afi, prefix_list_str); + if (plist == NULL) + { + vty_out (vty, "%% %s is not a valid prefix-list name%s", + prefix_list_str, VTY_NEWLINE); + return CMD_WARNING; + } + + vty->output_arg = plist; + + return bgp_show (vty, NULL, afi, safi, type); +} + +DEFUN (show_ip_bgp_prefix_list, + show_ip_bgp_prefix_list_cmd, + "show ip bgp prefix-list WORD", + SHOW_STR + IP_STR + BGP_STR + "Display routes conforming to the prefix-list\n" + "IP prefix-list name\n") +{ + return bgp_show_prefix_list (vty, argv[0], AFI_IP, SAFI_UNICAST, + bgp_show_type_prefix_list); +} + +DEFUN (show_ip_bgp_flap_prefix_list, + show_ip_bgp_flap_prefix_list_cmd, + "show ip bgp flap-statistics prefix-list WORD", + SHOW_STR + IP_STR + BGP_STR + "Display flap statistics of routes\n" + "Display routes conforming to the prefix-list\n" + "IP prefix-list name\n") +{ + return bgp_show_prefix_list (vty, argv[0], AFI_IP, SAFI_UNICAST, + bgp_show_type_flap_prefix_list); +} + +DEFUN (show_ip_bgp_ipv4_prefix_list, + show_ip_bgp_ipv4_prefix_list_cmd, + "show ip bgp ipv4 (unicast|multicast) prefix-list WORD", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes conforming to the prefix-list\n" + "IP prefix-list name\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_prefix_list (vty, argv[1], AFI_IP, SAFI_MULTICAST, + bgp_show_type_prefix_list); + + return bgp_show_prefix_list (vty, argv[1], AFI_IP, SAFI_UNICAST, + bgp_show_type_prefix_list); +} + +#ifdef HAVE_IPV6 +DEFUN (show_bgp_prefix_list, + show_bgp_prefix_list_cmd, + "show bgp prefix-list WORD", + SHOW_STR + BGP_STR + "Display routes conforming to the prefix-list\n" + "IPv6 prefix-list name\n") +{ + return bgp_show_prefix_list (vty, argv[0], AFI_IP6, SAFI_UNICAST, + bgp_show_type_prefix_list); +} + +ALIAS (show_bgp_prefix_list, + show_bgp_ipv6_prefix_list_cmd, + "show bgp ipv6 prefix-list WORD", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes conforming to the prefix-list\n" + "IPv6 prefix-list name\n") + +/* old command */ +DEFUN (show_ipv6_bgp_prefix_list, + show_ipv6_bgp_prefix_list_cmd, + "show ipv6 bgp prefix-list WORD", + SHOW_STR + IPV6_STR + BGP_STR + "Display routes matching the prefix-list\n" + "IPv6 prefix-list name\n") +{ + return bgp_show_prefix_list (vty, argv[0], AFI_IP6, SAFI_UNICAST, + bgp_show_type_prefix_list); +} + +/* old command */ +DEFUN (show_ipv6_mbgp_prefix_list, + show_ipv6_mbgp_prefix_list_cmd, + "show ipv6 mbgp prefix-list WORD", + SHOW_STR + IPV6_STR + MBGP_STR + "Display routes matching the prefix-list\n" + "IPv6 prefix-list name\n") +{ + return bgp_show_prefix_list (vty, argv[0], AFI_IP6, SAFI_MULTICAST, + bgp_show_type_prefix_list); +} +#endif /* HAVE_IPV6 */ + +int +bgp_show_filter_list (struct vty *vty, char *filter, afi_t afi, + safi_t safi, enum bgp_show_type type) +{ + struct as_list *as_list; + + as_list = as_list_lookup (filter); + if (as_list == NULL) + { + vty_out (vty, "%% %s is not a valid AS-path access-list name%s", filter, VTY_NEWLINE); + return CMD_WARNING; + } + + vty->output_arg = as_list; + + return bgp_show (vty, NULL, afi, safi, type); +} + +DEFUN (show_ip_bgp_filter_list, + show_ip_bgp_filter_list_cmd, + "show ip bgp filter-list WORD", + SHOW_STR + IP_STR + BGP_STR + "Display routes conforming to the filter-list\n" + "Regular expression access list name\n") +{ + return bgp_show_filter_list (vty, argv[0], AFI_IP, SAFI_UNICAST, + bgp_show_type_filter_list); +} + +DEFUN (show_ip_bgp_flap_filter_list, + show_ip_bgp_flap_filter_list_cmd, + "show ip bgp flap-statistics filter-list WORD", + SHOW_STR + IP_STR + BGP_STR + "Display flap statistics of routes\n" + "Display routes conforming to the filter-list\n" + "Regular expression access list name\n") +{ + return bgp_show_filter_list (vty, argv[0], AFI_IP, SAFI_UNICAST, + bgp_show_type_flap_filter_list); +} + +DEFUN (show_ip_bgp_ipv4_filter_list, + show_ip_bgp_ipv4_filter_list_cmd, + "show ip bgp ipv4 (unicast|multicast) filter-list WORD", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes conforming to the filter-list\n" + "Regular expression access list name\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_filter_list (vty, argv[1], AFI_IP, SAFI_MULTICAST, + bgp_show_type_filter_list); + + return bgp_show_filter_list (vty, argv[1], AFI_IP, SAFI_UNICAST, + bgp_show_type_filter_list); +} + +#ifdef HAVE_IPV6 +DEFUN (show_bgp_filter_list, + show_bgp_filter_list_cmd, + "show bgp filter-list WORD", + SHOW_STR + BGP_STR + "Display routes conforming to the filter-list\n" + "Regular expression access list name\n") +{ + return bgp_show_filter_list (vty, argv[0], AFI_IP6, SAFI_UNICAST, + bgp_show_type_filter_list); +} + +ALIAS (show_bgp_filter_list, + show_bgp_ipv6_filter_list_cmd, + "show bgp ipv6 filter-list WORD", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes conforming to the filter-list\n" + "Regular expression access list name\n") + +/* old command */ +DEFUN (show_ipv6_bgp_filter_list, + show_ipv6_bgp_filter_list_cmd, + "show ipv6 bgp filter-list WORD", + SHOW_STR + IPV6_STR + BGP_STR + "Display routes conforming to the filter-list\n" + "Regular expression access list name\n") +{ + return bgp_show_filter_list (vty, argv[0], AFI_IP6, SAFI_UNICAST, + bgp_show_type_filter_list); +} + +/* old command */ +DEFUN (show_ipv6_mbgp_filter_list, + show_ipv6_mbgp_filter_list_cmd, + "show ipv6 mbgp filter-list WORD", + SHOW_STR + IPV6_STR + MBGP_STR + "Display routes conforming to the filter-list\n" + "Regular expression access list name\n") +{ + return bgp_show_filter_list (vty, argv[0], AFI_IP6, SAFI_MULTICAST, + bgp_show_type_filter_list); +} +#endif /* HAVE_IPV6 */ + +int +bgp_show_route_map (struct vty *vty, char *rmap_str, afi_t afi, + safi_t safi, enum bgp_show_type type) +{ + struct route_map *rmap; + + rmap = route_map_lookup_by_name (rmap_str); + if (! rmap) + { + vty_out (vty, "%% %s is not a valid route-map name%s", + rmap_str, VTY_NEWLINE); + return CMD_WARNING; + } + + vty->output_arg = rmap; + + return bgp_show (vty, NULL, afi, safi, type); +} + +DEFUN (show_ip_bgp_route_map, + show_ip_bgp_route_map_cmd, + "show ip bgp route-map WORD", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the route-map\n" + "A route-map to match on\n") +{ + return bgp_show_route_map (vty, argv[0], AFI_IP, SAFI_UNICAST, + bgp_show_type_route_map); +} + +DEFUN (show_ip_bgp_flap_route_map, + show_ip_bgp_flap_route_map_cmd, + "show ip bgp flap-statistics route-map WORD", + SHOW_STR + IP_STR + BGP_STR + "Display flap statistics of routes\n" + "Display routes matching the route-map\n" + "A route-map to match on\n") +{ + return bgp_show_route_map (vty, argv[0], AFI_IP, SAFI_UNICAST, + bgp_show_type_flap_route_map); +} + +DEFUN (show_ip_bgp_ipv4_route_map, + show_ip_bgp_ipv4_route_map_cmd, + "show ip bgp ipv4 (unicast|multicast) route-map WORD", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the route-map\n" + "A route-map to match on\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_route_map (vty, argv[1], AFI_IP, SAFI_MULTICAST, + bgp_show_type_route_map); + + return bgp_show_route_map (vty, argv[1], AFI_IP, SAFI_UNICAST, + bgp_show_type_route_map); +} + +DEFUN (show_bgp_route_map, + show_bgp_route_map_cmd, + "show bgp route-map WORD", + SHOW_STR + BGP_STR + "Display routes matching the route-map\n" + "A route-map to match on\n") +{ + return bgp_show_route_map (vty, argv[0], AFI_IP6, SAFI_UNICAST, + bgp_show_type_route_map); +} + +ALIAS (show_bgp_route_map, + show_bgp_ipv6_route_map_cmd, + "show bgp ipv6 route-map WORD", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes matching the route-map\n" + "A route-map to match on\n") + +DEFUN (show_ip_bgp_cidr_only, + show_ip_bgp_cidr_only_cmd, + "show ip bgp cidr-only", + SHOW_STR + IP_STR + BGP_STR + "Display only routes with non-natural netmasks\n") +{ + return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, + bgp_show_type_cidr_only); +} + +DEFUN (show_ip_bgp_flap_cidr_only, + show_ip_bgp_flap_cidr_only_cmd, + "show ip bgp flap-statistics cidr-only", + SHOW_STR + IP_STR + BGP_STR + "Display flap statistics of routes\n" + "Display only routes with non-natural netmasks\n") +{ + return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, + bgp_show_type_flap_cidr_only); +} + +DEFUN (show_ip_bgp_ipv4_cidr_only, + show_ip_bgp_ipv4_cidr_only_cmd, + "show ip bgp ipv4 (unicast|multicast) cidr-only", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display only routes with non-natural netmasks\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, + bgp_show_type_cidr_only); + + return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, + bgp_show_type_cidr_only); +} + +DEFUN (show_ip_bgp_community_all, + show_ip_bgp_community_all_cmd, + "show ip bgp community", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the communities\n") +{ + return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, + bgp_show_type_community_all); +} + +DEFUN (show_ip_bgp_ipv4_community_all, + show_ip_bgp_ipv4_community_all_cmd, + "show ip bgp ipv4 (unicast|multicast) community", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the communities\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, + bgp_show_type_community_all); + + return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, + bgp_show_type_community_all); +} + +#ifdef HAVE_IPV6 +DEFUN (show_bgp_community_all, + show_bgp_community_all_cmd, + "show bgp community", + SHOW_STR + BGP_STR + "Display routes matching the communities\n") +{ + return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST, + bgp_show_type_community_all); +} + +ALIAS (show_bgp_community_all, + show_bgp_ipv6_community_all_cmd, + "show bgp ipv6 community", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes matching the communities\n") + +/* old command */ +DEFUN (show_ipv6_bgp_community_all, + show_ipv6_bgp_community_all_cmd, + "show ipv6 bgp community", + SHOW_STR + IPV6_STR + BGP_STR + "Display routes matching the communities\n") +{ + return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST, + bgp_show_type_community_all); +} + +/* old command */ +DEFUN (show_ipv6_mbgp_community_all, + show_ipv6_mbgp_community_all_cmd, + "show ipv6 mbgp community", + SHOW_STR + IPV6_STR + MBGP_STR + "Display routes matching the communities\n") +{ + return bgp_show (vty, NULL, AFI_IP6, SAFI_MULTICAST, + bgp_show_type_community_all); +} +#endif /* HAVE_IPV6 */ + +int +bgp_show_community (struct vty *vty, int argc, char **argv, int exact, + u_int16_t afi, u_char safi) +{ + struct community *com; + struct buffer *b; + int i; + char *str; + int first = 0; + + b = buffer_new (1024); + for (i = 0; i < argc; i++) + { + if (first) + buffer_putc (b, ' '); + else + { + if ((strcmp (argv[i], "unicast") == 0) || (strcmp (argv[i], "multicast") == 0)) + continue; + first = 1; + } + + buffer_putstr (b, argv[i]); + } + buffer_putc (b, '\0'); + + str = buffer_getstr (b); + buffer_free (b); + + com = community_str2com (str); + free (str); + if (! com) + { + vty_out (vty, "%% Community malformed: %s", VTY_NEWLINE); + return CMD_WARNING; + } + + vty->output_arg = com; + + if (exact) + return bgp_show (vty, NULL, afi, safi, bgp_show_type_community_exact); + + return bgp_show (vty, NULL, afi, safi, bgp_show_type_community); +} + +DEFUN (show_ip_bgp_community, + show_ip_bgp_community_cmd, + "show ip bgp community (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") +{ + return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_UNICAST); +} + +ALIAS (show_ip_bgp_community, + show_ip_bgp_community2_cmd, + "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +ALIAS (show_ip_bgp_community, + show_ip_bgp_community3_cmd, + "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +ALIAS (show_ip_bgp_community, + show_ip_bgp_community4_cmd, + "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +DEFUN (show_ip_bgp_ipv4_community, + show_ip_bgp_ipv4_community_cmd, + "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_MULTICAST); + + return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_UNICAST); +} + +ALIAS (show_ip_bgp_ipv4_community, + show_ip_bgp_ipv4_community2_cmd, + "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +ALIAS (show_ip_bgp_ipv4_community, + show_ip_bgp_ipv4_community3_cmd, + "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +ALIAS (show_ip_bgp_ipv4_community, + show_ip_bgp_ipv4_community4_cmd, + "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +DEFUN (show_ip_bgp_community_exact, + show_ip_bgp_community_exact_cmd, + "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") +{ + return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_UNICAST); +} + +ALIAS (show_ip_bgp_community_exact, + show_ip_bgp_community2_exact_cmd, + "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +ALIAS (show_ip_bgp_community_exact, + show_ip_bgp_community3_exact_cmd, + "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +ALIAS (show_ip_bgp_community_exact, + show_ip_bgp_community4_exact_cmd, + "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +DEFUN (show_ip_bgp_ipv4_community_exact, + show_ip_bgp_ipv4_community_exact_cmd, + "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_MULTICAST); + + return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_UNICAST); +} + +ALIAS (show_ip_bgp_ipv4_community_exact, + show_ip_bgp_ipv4_community2_exact_cmd, + "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +ALIAS (show_ip_bgp_ipv4_community_exact, + show_ip_bgp_ipv4_community3_exact_cmd, + "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +ALIAS (show_ip_bgp_ipv4_community_exact, + show_ip_bgp_ipv4_community4_exact_cmd, + "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +#ifdef HAVE_IPV6 +DEFUN (show_bgp_community, + show_bgp_community_cmd, + "show bgp community (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") +{ + return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_UNICAST); +} + +ALIAS (show_bgp_community, + show_bgp_ipv6_community_cmd, + "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +ALIAS (show_bgp_community, + show_bgp_community2_cmd, + "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +ALIAS (show_bgp_community, + show_bgp_ipv6_community2_cmd, + "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +ALIAS (show_bgp_community, + show_bgp_community3_cmd, + "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +ALIAS (show_bgp_community, + show_bgp_ipv6_community3_cmd, + "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +ALIAS (show_bgp_community, + show_bgp_community4_cmd, + "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +ALIAS (show_bgp_community, + show_bgp_ipv6_community4_cmd, + "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +/* old command */ +DEFUN (show_ipv6_bgp_community, + show_ipv6_bgp_community_cmd, + "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IPV6_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") +{ + return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_UNICAST); +} + +/* old command */ +ALIAS (show_ipv6_bgp_community, + show_ipv6_bgp_community2_cmd, + "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IPV6_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +/* old command */ +ALIAS (show_ipv6_bgp_community, + show_ipv6_bgp_community3_cmd, + "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IPV6_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +/* old command */ +ALIAS (show_ipv6_bgp_community, + show_ipv6_bgp_community4_cmd, + "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IPV6_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +DEFUN (show_bgp_community_exact, + show_bgp_community_exact_cmd, + "show bgp community (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") +{ + return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_UNICAST); +} + +ALIAS (show_bgp_community_exact, + show_bgp_ipv6_community_exact_cmd, + "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +ALIAS (show_bgp_community_exact, + show_bgp_community2_exact_cmd, + "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +ALIAS (show_bgp_community_exact, + show_bgp_ipv6_community2_exact_cmd, + "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +ALIAS (show_bgp_community_exact, + show_bgp_community3_exact_cmd, + "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +ALIAS (show_bgp_community_exact, + show_bgp_ipv6_community3_exact_cmd, + "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +ALIAS (show_bgp_community_exact, + show_bgp_community4_exact_cmd, + "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +ALIAS (show_bgp_community_exact, + show_bgp_ipv6_community4_exact_cmd, + "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +/* old command */ +DEFUN (show_ipv6_bgp_community_exact, + show_ipv6_bgp_community_exact_cmd, + "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IPV6_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") +{ + return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_UNICAST); +} + +/* old command */ +ALIAS (show_ipv6_bgp_community_exact, + show_ipv6_bgp_community2_exact_cmd, + "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IPV6_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +/* old command */ +ALIAS (show_ipv6_bgp_community_exact, + show_ipv6_bgp_community3_exact_cmd, + "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IPV6_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +/* old command */ +ALIAS (show_ipv6_bgp_community_exact, + show_ipv6_bgp_community4_exact_cmd, + "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IPV6_STR + BGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +/* old command */ +DEFUN (show_ipv6_mbgp_community, + show_ipv6_mbgp_community_cmd, + "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IPV6_STR + MBGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") +{ + return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_MULTICAST); +} + +/* old command */ +ALIAS (show_ipv6_mbgp_community, + show_ipv6_mbgp_community2_cmd, + "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IPV6_STR + MBGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +/* old command */ +ALIAS (show_ipv6_mbgp_community, + show_ipv6_mbgp_community3_cmd, + "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IPV6_STR + MBGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +/* old command */ +ALIAS (show_ipv6_mbgp_community, + show_ipv6_mbgp_community4_cmd, + "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", + SHOW_STR + IPV6_STR + MBGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +/* old command */ +DEFUN (show_ipv6_mbgp_community_exact, + show_ipv6_mbgp_community_exact_cmd, + "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IPV6_STR + MBGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") +{ + return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_MULTICAST); +} + +/* old command */ +ALIAS (show_ipv6_mbgp_community_exact, + show_ipv6_mbgp_community2_exact_cmd, + "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IPV6_STR + MBGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +/* old command */ +ALIAS (show_ipv6_mbgp_community_exact, + show_ipv6_mbgp_community3_exact_cmd, + "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IPV6_STR + MBGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") + +/* old command */ +ALIAS (show_ipv6_mbgp_community_exact, + show_ipv6_mbgp_community4_exact_cmd, + "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", + SHOW_STR + IPV6_STR + MBGP_STR + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Exact match of the communities") +#endif /* HAVE_IPV6 */ + +int +bgp_show_community_list (struct vty *vty, char *com, int exact, + u_int16_t afi, u_char safi) +{ + struct community_list *list; + + list = community_list_lookup (bgp_clist, com, COMMUNITY_LIST_AUTO); + if (list == NULL) + { + vty_out (vty, "%% %s is not a valid community-list name%s", com, + VTY_NEWLINE); + return CMD_WARNING; + } + + vty->output_arg = list; + + if (exact) + return bgp_show (vty, NULL, afi, safi, bgp_show_type_community_list_exact); + + return bgp_show (vty, NULL, afi, safi, bgp_show_type_community_list); +} + +DEFUN (show_ip_bgp_community_list, + show_ip_bgp_community_list_cmd, + "show ip bgp community-list WORD", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the community-list\n" + "community-list name\n") +{ + return bgp_show_community_list (vty, argv[0], 0, AFI_IP, SAFI_UNICAST); +} + +DEFUN (show_ip_bgp_ipv4_community_list, + show_ip_bgp_ipv4_community_list_cmd, + "show ip bgp ipv4 (unicast|multicast) community-list WORD", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the community-list\n" + "community-list name\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_community_list (vty, argv[1], 0, AFI_IP, SAFI_MULTICAST); + + return bgp_show_community_list (vty, argv[1], 0, AFI_IP, SAFI_UNICAST); +} + +DEFUN (show_ip_bgp_community_list_exact, + show_ip_bgp_community_list_exact_cmd, + "show ip bgp community-list WORD exact-match", + SHOW_STR + IP_STR + BGP_STR + "Display routes matching the community-list\n" + "community-list name\n" + "Exact match of the communities\n") +{ + return bgp_show_community_list (vty, argv[0], 1, AFI_IP, SAFI_UNICAST); +} + +DEFUN (show_ip_bgp_ipv4_community_list_exact, + show_ip_bgp_ipv4_community_list_exact_cmd, + "show ip bgp ipv4 (unicast|multicast) community-list WORD exact-match", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the community-list\n" + "community-list name\n" + "Exact match of the communities\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_community_list (vty, argv[1], 1, AFI_IP, SAFI_MULTICAST); + + return bgp_show_community_list (vty, argv[1], 1, AFI_IP, SAFI_UNICAST); +} + +#ifdef HAVE_IPV6 +DEFUN (show_bgp_community_list, + show_bgp_community_list_cmd, + "show bgp community-list WORD", + SHOW_STR + BGP_STR + "Display routes matching the community-list\n" + "community-list name\n") +{ + return bgp_show_community_list (vty, argv[0], 0, AFI_IP6, SAFI_UNICAST); +} + +ALIAS (show_bgp_community_list, + show_bgp_ipv6_community_list_cmd, + "show bgp ipv6 community-list WORD", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes matching the community-list\n" + "community-list name\n") + +/* old command */ +DEFUN (show_ipv6_bgp_community_list, + show_ipv6_bgp_community_list_cmd, + "show ipv6 bgp community-list WORD", + SHOW_STR + IPV6_STR + BGP_STR + "Display routes matching the community-list\n" + "community-list name\n") +{ + return bgp_show_community_list (vty, argv[0], 0, AFI_IP6, SAFI_UNICAST); +} + +/* old command */ +DEFUN (show_ipv6_mbgp_community_list, + show_ipv6_mbgp_community_list_cmd, + "show ipv6 mbgp community-list WORD", + SHOW_STR + IPV6_STR + MBGP_STR + "Display routes matching the community-list\n" + "community-list name\n") +{ + return bgp_show_community_list (vty, argv[0], 0, AFI_IP6, SAFI_MULTICAST); +} + +DEFUN (show_bgp_community_list_exact, + show_bgp_community_list_exact_cmd, + "show bgp community-list WORD exact-match", + SHOW_STR + BGP_STR + "Display routes matching the community-list\n" + "community-list name\n" + "Exact match of the communities\n") +{ + return bgp_show_community_list (vty, argv[0], 1, AFI_IP6, SAFI_UNICAST); +} + +ALIAS (show_bgp_community_list_exact, + show_bgp_ipv6_community_list_exact_cmd, + "show bgp ipv6 community-list WORD exact-match", + SHOW_STR + BGP_STR + "Address family\n" + "Display routes matching the community-list\n" + "community-list name\n" + "Exact match of the communities\n") + +/* old command */ +DEFUN (show_ipv6_bgp_community_list_exact, + show_ipv6_bgp_community_list_exact_cmd, + "show ipv6 bgp community-list WORD exact-match", + SHOW_STR + IPV6_STR + BGP_STR + "Display routes matching the community-list\n" + "community-list name\n" + "Exact match of the communities\n") +{ + return bgp_show_community_list (vty, argv[0], 1, AFI_IP6, SAFI_UNICAST); +} + +/* old command */ +DEFUN (show_ipv6_mbgp_community_list_exact, + show_ipv6_mbgp_community_list_exact_cmd, + "show ipv6 mbgp community-list WORD exact-match", + SHOW_STR + IPV6_STR + MBGP_STR + "Display routes matching the community-list\n" + "community-list name\n" + "Exact match of the communities\n") +{ + return bgp_show_community_list (vty, argv[0], 1, AFI_IP6, SAFI_MULTICAST); +} +#endif /* HAVE_IPV6 */ + +void +bgp_show_prefix_longer_clean (struct vty *vty) +{ + struct prefix *p; + + p = vty->output_arg; + prefix_free (p); +} + +int +bgp_show_prefix_longer (struct vty *vty, char *prefix, afi_t afi, + safi_t safi, enum bgp_show_type type) +{ + int ret; + struct prefix *p; + + p = prefix_new(); + + ret = str2prefix (prefix, p); + if (! ret) + { + vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + vty->output_arg = p; + vty->output_clean = bgp_show_prefix_longer_clean; + + return bgp_show (vty, NULL, afi, safi, type); +} + +DEFUN (show_ip_bgp_prefix_longer, + show_ip_bgp_prefix_longer_cmd, + "show ip bgp A.B.C.D/M longer-prefixes", + SHOW_STR + IP_STR + BGP_STR + "IP prefix /, e.g., 35.0.0.0/8\n" + "Display route and more specific routes\n") +{ + return bgp_show_prefix_longer (vty, argv[0], AFI_IP, SAFI_UNICAST, + bgp_show_type_prefix_longer); +} + +DEFUN (show_ip_bgp_flap_prefix_longer, + show_ip_bgp_flap_prefix_longer_cmd, + "show ip bgp flap-statistics A.B.C.D/M longer-prefixes", + SHOW_STR + IP_STR + BGP_STR + "Display flap statistics of routes\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Display route and more specific routes\n") +{ + return bgp_show_prefix_longer (vty, argv[0], AFI_IP, SAFI_UNICAST, + bgp_show_type_flap_prefix_longer); +} + +DEFUN (show_ip_bgp_ipv4_prefix_longer, + show_ip_bgp_ipv4_prefix_longer_cmd, + "show ip bgp ipv4 (unicast|multicast) A.B.C.D/M longer-prefixes", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Display route and more specific routes\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_prefix_longer (vty, argv[1], AFI_IP, SAFI_MULTICAST, + bgp_show_type_prefix_longer); + + return bgp_show_prefix_longer (vty, argv[1], AFI_IP, SAFI_UNICAST, + bgp_show_type_prefix_longer); +} + +DEFUN (show_ip_bgp_flap_address, + show_ip_bgp_flap_address_cmd, + "show ip bgp flap-statistics A.B.C.D", + SHOW_STR + IP_STR + BGP_STR + "Display flap statistics of routes\n" + "Network in the BGP routing table to display\n") +{ + return bgp_show_prefix_longer (vty, argv[0], AFI_IP, SAFI_UNICAST, + bgp_show_type_flap_address); +} + +DEFUN (show_ip_bgp_flap_prefix, + show_ip_bgp_flap_prefix_cmd, + "show ip bgp flap-statistics A.B.C.D/M", + SHOW_STR + IP_STR + BGP_STR + "Display flap statistics of routes\n" + "IP prefix /, e.g., 35.0.0.0/8\n") +{ + return bgp_show_prefix_longer (vty, argv[0], AFI_IP, SAFI_UNICAST, + bgp_show_type_flap_prefix); +} +#ifdef HAVE_IPV6 +DEFUN (show_bgp_prefix_longer, + show_bgp_prefix_longer_cmd, + "show bgp X:X::X:X/M longer-prefixes", + SHOW_STR + BGP_STR + "IPv6 prefix /\n" + "Display route and more specific routes\n") +{ + return bgp_show_prefix_longer (vty, argv[0], AFI_IP6, SAFI_UNICAST, + bgp_show_type_prefix_longer); +} + +ALIAS (show_bgp_prefix_longer, + show_bgp_ipv6_prefix_longer_cmd, + "show bgp ipv6 X:X::X:X/M longer-prefixes", + SHOW_STR + BGP_STR + "Address family\n" + "IPv6 prefix /\n" + "Display route and more specific routes\n") + +/* old command */ +DEFUN (show_ipv6_bgp_prefix_longer, + show_ipv6_bgp_prefix_longer_cmd, + "show ipv6 bgp X:X::X:X/M longer-prefixes", + SHOW_STR + IPV6_STR + BGP_STR + "IPv6 prefix /, e.g., 3ffe::/16\n" + "Display route and more specific routes\n") +{ + return bgp_show_prefix_longer (vty, argv[0], AFI_IP6, SAFI_UNICAST, + bgp_show_type_prefix_longer); +} + +/* old command */ +DEFUN (show_ipv6_mbgp_prefix_longer, + show_ipv6_mbgp_prefix_longer_cmd, + "show ipv6 mbgp X:X::X:X/M longer-prefixes", + SHOW_STR + IPV6_STR + MBGP_STR + "IPv6 prefix /, e.g., 3ffe::/16\n" + "Display route and more specific routes\n") +{ + return bgp_show_prefix_longer (vty, argv[0], AFI_IP6, SAFI_MULTICAST, + bgp_show_type_prefix_longer); +} +#endif /* HAVE_IPV6 */ + +void +show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, + int in) +{ + struct bgp_table *table; + struct bgp_adj_in *ain; + struct bgp_adj_out *adj; + unsigned long output_count; + struct bgp_node *rn; + int header1 = 1; + struct bgp *bgp; + int header2 = 1; + + bgp = bgp_get_default (); + + if (! bgp) + return; + + table = bgp->rib[afi][safi]; + + output_count = 0; + + if (! in && CHECK_FLAG (peer->af_sflags[afi][safi], + PEER_STATUS_DEFAULT_ORIGINATE)) + { + vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE); + vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s", VTY_NEWLINE); + vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s", VTY_NEWLINE, VTY_NEWLINE); + + vty_out (vty, "Originating default network 0.0.0.0%s%s", + VTY_NEWLINE, VTY_NEWLINE); + header1 = 0; + } + + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + if (in) + { + for (ain = rn->adj_in; ain; ain = ain->next) + if (ain->peer == peer) + { + if (header1) + { + vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE); + vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s", VTY_NEWLINE); + vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s", VTY_NEWLINE, VTY_NEWLINE); + header1 = 0; + } + if (header2) + { + vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE); + header2 = 0; + } + if (ain->attr) + { + route_vty_out_tmp (vty, &rn->p, ain->attr, safi); + output_count++; + } + } + } + else + { + for (adj = rn->adj_out; adj; adj = adj->next) + if (adj->peer == peer) + { + if (header1) + { + vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE); + vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s", VTY_NEWLINE); + vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s", VTY_NEWLINE, VTY_NEWLINE); + header1 = 0; + } + if (header2) + { + vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE); + header2 = 0; + } + if (adj->attr) + { + route_vty_out_tmp (vty, &rn->p, adj->attr, safi); + output_count++; + } + } + } + + if (output_count != 0) + vty_out (vty, "%sTotal number of prefixes %ld%s", + VTY_NEWLINE, output_count, VTY_NEWLINE); +} + +int +peer_adj_routes (struct vty *vty, char *ip_str, afi_t afi, safi_t safi, int in) +{ + int ret; + struct peer *peer; + union sockunion su; + + ret = str2sockunion (ip_str, &su); + if (ret < 0) + { + vty_out (vty, "Malformed address: %s%s", ip_str, VTY_NEWLINE); + return CMD_WARNING; + } + peer = peer_lookup (NULL, &su); + if (! peer || ! peer->afc[afi][safi]) + { + vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (in && ! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) + { + vty_out (vty, "%% Inbound soft reconfiguration not enabled%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + show_adj_route (vty, peer, afi, safi, in); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_bgp_neighbor_advertised_route, + show_ip_bgp_neighbor_advertised_route_cmd, + "show ip bgp neighbors (A.B.C.D|X:X::X:X) advertised-routes", + SHOW_STR + IP_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display the routes advertised to a BGP neighbor\n") +{ + return peer_adj_routes (vty, argv[0], AFI_IP, SAFI_UNICAST, 0); +} + +DEFUN (show_ip_bgp_ipv4_neighbor_advertised_route, + show_ip_bgp_ipv4_neighbor_advertised_route_cmd, + "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) advertised-routes", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display the routes advertised to a BGP neighbor\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return peer_adj_routes (vty, argv[1], AFI_IP, SAFI_MULTICAST, 0); + + return peer_adj_routes (vty, argv[1], AFI_IP, SAFI_UNICAST, 0); +} + +#ifdef HAVE_IPV6 +DEFUN (show_bgp_neighbor_advertised_route, + show_bgp_neighbor_advertised_route_cmd, + "show bgp neighbors (A.B.C.D|X:X::X:X) advertised-routes", + SHOW_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display the routes advertised to a BGP neighbor\n") +{ + return peer_adj_routes (vty, argv[0], AFI_IP6, SAFI_UNICAST, 0); +} + +ALIAS (show_bgp_neighbor_advertised_route, + show_bgp_ipv6_neighbor_advertised_route_cmd, + "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) advertised-routes", + SHOW_STR + BGP_STR + "Address family\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display the routes advertised to a BGP neighbor\n") + +/* old command */ +DEFUN (ipv6_bgp_neighbor_advertised_route, + ipv6_bgp_neighbor_advertised_route_cmd, + "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X) advertised-routes", + SHOW_STR + IPV6_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display the routes advertised to a BGP neighbor\n") +{ + return peer_adj_routes (vty, argv[0], AFI_IP6, SAFI_UNICAST, 0); +} + +/* old command */ +DEFUN (ipv6_mbgp_neighbor_advertised_route, + ipv6_mbgp_neighbor_advertised_route_cmd, + "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X) advertised-routes", + SHOW_STR + IPV6_STR + MBGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display the routes advertised to a BGP neighbor\n") +{ + return peer_adj_routes (vty, argv[0], AFI_IP6, SAFI_MULTICAST, 0); +} +#endif /* HAVE_IPV6 */ + +DEFUN (show_ip_bgp_neighbor_received_routes, + show_ip_bgp_neighbor_received_routes_cmd, + "show ip bgp neighbors (A.B.C.D|X:X::X:X) received-routes", + SHOW_STR + IP_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display the received routes from neighbor\n") +{ + return peer_adj_routes (vty, argv[0], AFI_IP, SAFI_UNICAST, 1); +} + +DEFUN (show_ip_bgp_ipv4_neighbor_received_routes, + show_ip_bgp_ipv4_neighbor_received_routes_cmd, + "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) received-routes", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display the received routes from neighbor\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return peer_adj_routes (vty, argv[1], AFI_IP, SAFI_MULTICAST, 1); + + return peer_adj_routes (vty, argv[1], AFI_IP, SAFI_UNICAST, 1); +} + +DEFUN (show_ip_bgp_neighbor_received_prefix_filter, + show_ip_bgp_neighbor_received_prefix_filter_cmd, + "show ip bgp neighbors (A.B.C.D|X:X::X:X) received prefix-filter", + SHOW_STR + IP_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display information received from a BGP neighbor\n" + "Display the prefixlist filter\n") +{ + char name[BUFSIZ]; + union sockunion *su; + struct peer *peer; + int count; + + su = sockunion_str2su (argv[0]); + if (su == NULL) + return CMD_WARNING; + + peer = peer_lookup (NULL, su); + if (! peer) + return CMD_WARNING; + + sprintf (name, "%s.%d.%d", peer->host, AFI_IP, SAFI_UNICAST); + count = prefix_bgp_show_prefix_list (NULL, AFI_IP, name); + if (count) + { + vty_out (vty, "Address family: IPv4 Unicast%s", VTY_NEWLINE); + prefix_bgp_show_prefix_list (vty, AFI_IP, name); + } + + return CMD_SUCCESS; +} + +DEFUN (show_ip_bgp_ipv4_neighbor_received_prefix_filter, + show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd, + "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) received prefix-filter", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display information received from a BGP neighbor\n" + "Display the prefixlist filter\n") +{ + char name[BUFSIZ]; + union sockunion *su; + struct peer *peer; + int count; + + su = sockunion_str2su (argv[1]); + if (su == NULL) + return CMD_WARNING; + + peer = peer_lookup (NULL, su); + if (! peer) + return CMD_WARNING; + + if (strncmp (argv[0], "m", 1) == 0) + { + sprintf (name, "%s.%d.%d", peer->host, AFI_IP, SAFI_MULTICAST); + count = prefix_bgp_show_prefix_list (NULL, AFI_IP, name); + if (count) + { + vty_out (vty, "Address family: IPv4 Multicast%s", VTY_NEWLINE); + prefix_bgp_show_prefix_list (vty, AFI_IP, name); + } + } + else + { + sprintf (name, "%s.%d.%d", peer->host, AFI_IP, SAFI_UNICAST); + count = prefix_bgp_show_prefix_list (NULL, AFI_IP, name); + if (count) + { + vty_out (vty, "Address family: IPv4 Unicast%s", VTY_NEWLINE); + prefix_bgp_show_prefix_list (vty, AFI_IP, name); + } + } + + return CMD_SUCCESS; +} + + +#ifdef HAVE_IPV6 +DEFUN (show_bgp_neighbor_received_routes, + show_bgp_neighbor_received_routes_cmd, + "show bgp neighbors (A.B.C.D|X:X::X:X) received-routes", + SHOW_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display the received routes from neighbor\n") +{ + return peer_adj_routes (vty, argv[0], AFI_IP6, SAFI_UNICAST, 1); +} + +ALIAS (show_bgp_neighbor_received_routes, + show_bgp_ipv6_neighbor_received_routes_cmd, + "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) received-routes", + SHOW_STR + BGP_STR + "Address family\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display the received routes from neighbor\n") + +DEFUN (show_bgp_neighbor_received_prefix_filter, + show_bgp_neighbor_received_prefix_filter_cmd, + "show bgp neighbors (A.B.C.D|X:X::X:X) received prefix-filter", + SHOW_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display information received from a BGP neighbor\n" + "Display the prefixlist filter\n") +{ + char name[BUFSIZ]; + union sockunion *su; + struct peer *peer; + int count; + + su = sockunion_str2su (argv[0]); + if (su == NULL) + return CMD_WARNING; + + peer = peer_lookup (NULL, su); + if (! peer) + return CMD_WARNING; + + sprintf (name, "%s.%d.%d", peer->host, AFI_IP6, SAFI_UNICAST); + count = prefix_bgp_show_prefix_list (NULL, AFI_IP6, name); + if (count) + { + vty_out (vty, "Address family: IPv6 Unicast%s", VTY_NEWLINE); + prefix_bgp_show_prefix_list (vty, AFI_IP6, name); + } + + return CMD_SUCCESS; +} + +ALIAS (show_bgp_neighbor_received_prefix_filter, + show_bgp_ipv6_neighbor_received_prefix_filter_cmd, + "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) received prefix-filter", + SHOW_STR + BGP_STR + "Address family\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display information received from a BGP neighbor\n" + "Display the prefixlist filter\n") + +/* old command */ +DEFUN (ipv6_bgp_neighbor_received_routes, + ipv6_bgp_neighbor_received_routes_cmd, + "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X) received-routes", + SHOW_STR + IPV6_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display the received routes from neighbor\n") +{ + return peer_adj_routes (vty, argv[0], AFI_IP6, SAFI_UNICAST, 1); +} + +/* old command */ +DEFUN (ipv6_mbgp_neighbor_received_routes, + ipv6_mbgp_neighbor_received_routes_cmd, + "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X) received-routes", + SHOW_STR + IPV6_STR + MBGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display the received routes from neighbor\n") +{ + return peer_adj_routes (vty, argv[0], AFI_IP6, SAFI_MULTICAST, 1); +} +#endif /* HAVE_IPV6 */ + +void +bgp_show_neighbor_route_clean (struct vty *vty) +{ + union sockunion *su; + + su = vty->output_arg; + XFREE (MTYPE_SOCKUNION, su); +} + +int +bgp_show_neighbor_route (struct vty *vty, char *ip_str, afi_t afi, + safi_t safi, enum bgp_show_type type) +{ + union sockunion *su; + struct peer *peer; + + su = sockunion_str2su (ip_str); + if (su == NULL) + { + vty_out (vty, "Malformed address: %s%s", ip_str, VTY_NEWLINE); + return CMD_WARNING; + } + + peer = peer_lookup (NULL, su); + if (! peer || ! peer->afc[afi][safi]) + { + vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); + XFREE (MTYPE_SOCKUNION, su); + return CMD_WARNING; + } + + vty->output_arg = su; + vty->output_clean = bgp_show_neighbor_route_clean; + + return bgp_show (vty, NULL, afi, safi, type); +} + +DEFUN (show_ip_bgp_neighbor_routes, + show_ip_bgp_neighbor_routes_cmd, + "show ip bgp neighbors (A.B.C.D|X:X::X:X) routes", + SHOW_STR + IP_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display routes learned from neighbor\n") +{ + return bgp_show_neighbor_route (vty, argv[0], AFI_IP, SAFI_UNICAST, + bgp_show_type_neighbor); +} + +DEFUN (show_ip_bgp_neighbor_flap, + show_ip_bgp_neighbor_flap_cmd, + "show ip bgp neighbors (A.B.C.D|X:X::X:X) flap-statistics", + SHOW_STR + IP_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display flap statistics of the routes learned from neighbor\n") +{ + return bgp_show_neighbor_route (vty, argv[0], AFI_IP, SAFI_UNICAST, + bgp_show_type_flap_neighbor); +} + +DEFUN (show_ip_bgp_neighbor_damp, + show_ip_bgp_neighbor_damp_cmd, + "show ip bgp neighbors (A.B.C.D|X:X::X:X) dampened-routes", + SHOW_STR + IP_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display the dampened routes received from neighbor\n") +{ + return bgp_show_neighbor_route (vty, argv[0], AFI_IP, SAFI_UNICAST, + bgp_show_type_damp_neighbor); +} + +DEFUN (show_ip_bgp_ipv4_neighbor_routes, + show_ip_bgp_ipv4_neighbor_routes_cmd, + "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) routes", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display routes learned from neighbor\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_neighbor_route (vty, argv[1], AFI_IP, SAFI_MULTICAST, + bgp_show_type_neighbor); + + return bgp_show_neighbor_route (vty, argv[1], AFI_IP, SAFI_UNICAST, + bgp_show_type_neighbor); +} +#ifdef HAVE_IPV6 +DEFUN (show_bgp_neighbor_routes, + show_bgp_neighbor_routes_cmd, + "show bgp neighbors (A.B.C.D|X:X::X:X) routes", + SHOW_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display routes learned from neighbor\n") +{ + return bgp_show_neighbor_route (vty, argv[0], AFI_IP6, SAFI_UNICAST, + bgp_show_type_neighbor); +} + +ALIAS (show_bgp_neighbor_routes, + show_bgp_ipv6_neighbor_routes_cmd, + "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) routes", + SHOW_STR + BGP_STR + "Address family\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display routes learned from neighbor\n") + +/* old command */ +DEFUN (ipv6_bgp_neighbor_routes, + ipv6_bgp_neighbor_routes_cmd, + "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X) routes", + SHOW_STR + IPV6_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display routes learned from neighbor\n") +{ + return bgp_show_neighbor_route (vty, argv[0], AFI_IP6, SAFI_UNICAST, + bgp_show_type_neighbor); +} + +/* old command */ +DEFUN (ipv6_mbgp_neighbor_routes, + ipv6_mbgp_neighbor_routes_cmd, + "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X) routes", + SHOW_STR + IPV6_STR + MBGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display routes learned from neighbor\n") +{ + return bgp_show_neighbor_route (vty, argv[0], AFI_IP6, SAFI_MULTICAST, + bgp_show_type_neighbor); +} +#endif /* HAVE_IPV6 */ + +struct bgp_table *bgp_distance_table; + +struct bgp_distance +{ + /* Distance value for the IP source prefix. */ + u_char distance; + + /* Name of the access-list to be matched. */ + char *access_list; +}; + +struct bgp_distance * +bgp_distance_new () +{ + struct bgp_distance *new; + new = XMALLOC (MTYPE_BGP_DISTANCE, sizeof (struct bgp_distance)); + memset (new, 0, sizeof (struct bgp_distance)); + return new; +} + +void +bgp_distance_free (struct bgp_distance *bdistance) +{ + XFREE (MTYPE_BGP_DISTANCE, bdistance); +} + +int +bgp_distance_set (struct vty *vty, char *distance_str, char *ip_str, + char *access_list_str) +{ + int ret; + struct prefix_ipv4 p; + u_char distance; + struct bgp_node *rn; + struct bgp_distance *bdistance; + + ret = str2prefix_ipv4 (ip_str, &p); + if (ret == 0) + { + vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + distance = atoi (distance_str); + + /* Get BGP distance node. */ + rn = bgp_node_get (bgp_distance_table, (struct prefix *) &p); + if (rn->info) + { + bdistance = rn->info; + bgp_unlock_node (rn); + } + else + { + bdistance = bgp_distance_new (); + rn->info = bdistance; + } + + /* Set distance value. */ + bdistance->distance = distance; + + /* Reset access-list configuration. */ + if (bdistance->access_list) + { + free (bdistance->access_list); + bdistance->access_list = NULL; + } + if (access_list_str) + bdistance->access_list = strdup (access_list_str); + + return CMD_SUCCESS; +} + +int +bgp_distance_unset (struct vty *vty, char *distance_str, char *ip_str, + char *access_list_str) +{ + int ret; + struct prefix_ipv4 p; + u_char distance; + struct bgp_node *rn; + struct bgp_distance *bdistance; + + ret = str2prefix_ipv4 (ip_str, &p); + if (ret == 0) + { + vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + distance = atoi (distance_str); + + rn = bgp_node_lookup (bgp_distance_table, (struct prefix *)&p); + if (! rn) + { + vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + bdistance = rn->info; + + if (bdistance->access_list) + free (bdistance->access_list); + bgp_distance_free (bdistance); + + rn->info = NULL; + bgp_unlock_node (rn); + bgp_unlock_node (rn); + + return CMD_SUCCESS; +} + +void +bgp_distance_reset () +{ + struct bgp_node *rn; + struct bgp_distance *bdistance; + + for (rn = bgp_table_top (bgp_distance_table); rn; rn = bgp_route_next (rn)) + if ((bdistance = rn->info) != NULL) + { + if (bdistance->access_list) + free (bdistance->access_list); + bgp_distance_free (bdistance); + rn->info = NULL; + bgp_unlock_node (rn); + } +} + +/* Apply BGP information to distance method. */ +u_char +bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp) +{ + struct bgp_node *rn; + struct prefix_ipv4 q; + struct peer *peer; + struct bgp_distance *bdistance; + struct access_list *alist; + struct bgp_static *bgp_static; + + if (! bgp) + return 0; + + if (p->family != AF_INET) + return 0; + + peer = rinfo->peer; + + if (peer->su.sa.sa_family != AF_INET) + return 0; + + memset (&q, 0, sizeof (struct prefix_ipv4)); + q.family = AF_INET; + q.prefix = peer->su.sin.sin_addr; + q.prefixlen = IPV4_MAX_BITLEN; + + /* Check source address. */ + rn = bgp_node_match (bgp_distance_table, (struct prefix *) &q); + if (rn) + { + bdistance = rn->info; + bgp_unlock_node (rn); + + if (bdistance->access_list) + { + alist = access_list_lookup (AFI_IP, bdistance->access_list); + if (alist && access_list_apply (alist, p) == FILTER_PERMIT) + return bdistance->distance; + } + else + return bdistance->distance; + } + + /* Backdoor check. */ + rn = bgp_node_lookup (bgp->route[AFI_IP][SAFI_UNICAST], p); + if (rn) + { + bgp_static = rn->info; + bgp_unlock_node (rn); + + if (bgp_static->backdoor) + { + if (bgp->distance_local) + return bgp->distance_local; + else + return ZEBRA_IBGP_DISTANCE_DEFAULT; + } + } + + if (peer_sort (peer) == BGP_PEER_EBGP) + { + if (bgp->distance_ebgp) + return bgp->distance_ebgp; + return ZEBRA_EBGP_DISTANCE_DEFAULT; + } + else + { + if (bgp->distance_ibgp) + return bgp->distance_ibgp; + return ZEBRA_IBGP_DISTANCE_DEFAULT; + } +} + +DEFUN (bgp_distance, + bgp_distance_cmd, + "distance bgp <1-255> <1-255> <1-255>", + "Define an administrative distance\n" + "BGP distance\n" + "Distance for routes external to the AS\n" + "Distance for routes internal to the AS\n" + "Distance for local routes\n") +{ + struct bgp *bgp; + + bgp = vty->index; + + bgp->distance_ebgp = atoi (argv[0]); + bgp->distance_ibgp = atoi (argv[1]); + bgp->distance_local = atoi (argv[2]); + return CMD_SUCCESS; +} + +DEFUN (no_bgp_distance, + no_bgp_distance_cmd, + "no distance bgp <1-255> <1-255> <1-255>", + NO_STR + "Define an administrative distance\n" + "BGP distance\n" + "Distance for routes external to the AS\n" + "Distance for routes internal to the AS\n" + "Distance for local routes\n") +{ + struct bgp *bgp; + + bgp = vty->index; + + bgp->distance_ebgp= 0; + bgp->distance_ibgp = 0; + bgp->distance_local = 0; + return CMD_SUCCESS; +} + +ALIAS (no_bgp_distance, + no_bgp_distance2_cmd, + "no distance bgp", + NO_STR + "Define an administrative distance\n" + "BGP distance\n") + +DEFUN (bgp_distance_source, + bgp_distance_source_cmd, + "distance <1-255> A.B.C.D/M", + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n") +{ + bgp_distance_set (vty, argv[0], argv[1], NULL); + return CMD_SUCCESS; +} + +DEFUN (no_bgp_distance_source, + no_bgp_distance_source_cmd, + "no distance <1-255> A.B.C.D/M", + NO_STR + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n") +{ + bgp_distance_unset (vty, argv[0], argv[1], NULL); + return CMD_SUCCESS; +} + +DEFUN (bgp_distance_source_access_list, + bgp_distance_source_access_list_cmd, + "distance <1-255> A.B.C.D/M WORD", + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n" + "Access list name\n") +{ + bgp_distance_set (vty, argv[0], argv[1], argv[2]); + return CMD_SUCCESS; +} + +DEFUN (no_bgp_distance_source_access_list, + no_bgp_distance_source_access_list_cmd, + "no distance <1-255> A.B.C.D/M WORD", + NO_STR + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n" + "Access list name\n") +{ + bgp_distance_unset (vty, argv[0], argv[1], argv[2]); + return CMD_SUCCESS; +} + +DEFUN (bgp_damp_set, + bgp_damp_set_cmd, + "bgp dampening <1-45> <1-20000> <1-20000> <1-255>", + "BGP Specific commands\n" + "Enable route-flap dampening\n" + "Half-life time for the penalty\n" + "Value to start reusing a route\n" + "Value to start suppressing a route\n" + "Maximum duration to suppress a stable route\n") +{ + struct bgp *bgp; + int half = DEFAULT_HALF_LIFE * 60; + int reuse = DEFAULT_REUSE; + int suppress = DEFAULT_SUPPRESS; + int max = 4 * half; + + if (argc == 4) + { + half = atoi (argv[0]) * 60; + reuse = atoi (argv[1]); + suppress = atoi (argv[2]); + max = atoi (argv[3]) * 60; + } + else if (argc == 1) + { + half = atoi (argv[0]) * 60; + max = 4 * half; + } + + bgp = vty->index; + return bgp_damp_enable (bgp, bgp_node_afi (vty), bgp_node_safi (vty), + half, reuse, suppress, max); +} + +ALIAS (bgp_damp_set, + bgp_damp_set2_cmd, + "bgp dampening <1-45>", + "BGP Specific commands\n" + "Enable route-flap dampening\n" + "Half-life time for the penalty\n") + +ALIAS (bgp_damp_set, + bgp_damp_set3_cmd, + "bgp dampening", + "BGP Specific commands\n" + "Enable route-flap dampening\n") + +DEFUN (bgp_damp_unset, + bgp_damp_unset_cmd, + "no bgp dampening", + NO_STR + "BGP Specific commands\n" + "Enable route-flap dampening\n") +{ + struct bgp *bgp; + + bgp = vty->index; + return bgp_damp_disable (bgp, bgp_node_afi (vty), bgp_node_safi (vty)); +} + +ALIAS (bgp_damp_unset, + bgp_damp_unset2_cmd, + "no bgp dampening <1-45> <1-20000> <1-20000> <1-255>", + NO_STR + "BGP Specific commands\n" + "Enable route-flap dampening\n" + "Half-life time for the penalty\n" + "Value to start reusing a route\n" + "Value to start suppressing a route\n" + "Maximum duration to suppress a stable route\n") + +DEFUN (show_ip_bgp_dampened_paths, + show_ip_bgp_dampened_paths_cmd, + "show ip bgp dampened-paths", + SHOW_STR + IP_STR + BGP_STR + "Display paths suppressed due to dampening\n") +{ + return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_dampend_paths); +} + +DEFUN (show_ip_bgp_flap_statistics, + show_ip_bgp_flap_statistics_cmd, + "show ip bgp flap-statistics", + SHOW_STR + IP_STR + BGP_STR + "Display flap statistics of routes\n") +{ + return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_flap_statistics); +} + +/* Display specified route of BGP table. */ +int +bgp_clear_damp_route (struct vty *vty, char *view_name, char *ip_str, + afi_t afi, safi_t safi, struct prefix_rd *prd, + int prefix_check) +{ + int ret; + struct prefix match; + struct bgp_node *rn; + struct bgp_node *rm; + struct bgp_info *ri; + struct bgp_info *ri_temp; + struct bgp *bgp; + struct bgp_table *table; + + /* BGP structure lookup. */ + if (view_name) + { + bgp = bgp_lookup_by_name (view_name); + if (bgp == NULL) + { + vty_out (vty, "%% Can't find BGP view %s%s", view_name, VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + bgp = bgp_get_default (); + if (bgp == NULL) + { + vty_out (vty, "%% No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + + /* Check IP address argument. */ + ret = str2prefix (ip_str, &match); + if (! ret) + { + vty_out (vty, "%% address is malformed%s", VTY_NEWLINE); + return CMD_WARNING; + } + + match.family = afi2family (afi); + + if (safi == SAFI_MPLS_VPN) + { + for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn)) + { + if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) + continue; + + if ((table = rn->info) != NULL) + if ((rm = bgp_node_match (table, &match)) != NULL) + if (! prefix_check || rm->p.prefixlen == match.prefixlen) + { + ri = rm->info; + while (ri) + { + if (ri->damp_info) + { + ri_temp = ri->next; + bgp_damp_info_free (ri->damp_info, 1); + ri = ri_temp; + } + else + ri = ri->next; + } + } + } + } + else + { + if ((rn = bgp_node_match (bgp->rib[afi][safi], &match)) != NULL) + if (! prefix_check || rn->p.prefixlen == match.prefixlen) + { + ri = rn->info; + while (ri) + { + if (ri->damp_info) + { + ri_temp = ri->next; + bgp_damp_info_free (ri->damp_info, 1); + ri = ri_temp; + } + else + ri = ri->next; + } + } + } + + return CMD_SUCCESS; +} + +DEFUN (clear_ip_bgp_dampening, + clear_ip_bgp_dampening_cmd, + "clear ip bgp dampening", + CLEAR_STR + IP_STR + BGP_STR + "Clear route flap dampening information\n") +{ + bgp_damp_info_clean (); + return CMD_SUCCESS; +} + +DEFUN (clear_ip_bgp_dampening_prefix, + clear_ip_bgp_dampening_prefix_cmd, + "clear ip bgp dampening A.B.C.D/M", + CLEAR_STR + IP_STR + BGP_STR + "Clear route flap dampening information\n" + "IP prefix /, e.g., 35.0.0.0/8\n") +{ + return bgp_clear_damp_route (vty, NULL, argv[0], AFI_IP, + SAFI_UNICAST, NULL, 1); +} + +DEFUN (clear_ip_bgp_dampening_address, + clear_ip_bgp_dampening_address_cmd, + "clear ip bgp dampening A.B.C.D", + CLEAR_STR + IP_STR + BGP_STR + "Clear route flap dampening information\n" + "Network to clear damping information\n") +{ + return bgp_clear_damp_route (vty, NULL, argv[0], AFI_IP, + SAFI_UNICAST, NULL, 0); +} + +DEFUN (clear_ip_bgp_dampening_address_mask, + clear_ip_bgp_dampening_address_mask_cmd, + "clear ip bgp dampening A.B.C.D A.B.C.D", + CLEAR_STR + IP_STR + BGP_STR + "Clear route flap dampening information\n" + "Network to clear damping information\n" + "Network mask\n") +{ + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str); + if (! ret) + { + vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_clear_damp_route (vty, NULL, prefix_str, AFI_IP, + SAFI_UNICAST, NULL, 0); +} + +int +bgp_config_write_network_vpnv4 (struct vty *vty, struct bgp *bgp, + afi_t afi, safi_t safi, int *write) +{ + struct bgp_node *prn; + struct bgp_node *rn; + struct bgp_table *table; + struct prefix *p; + struct prefix_rd *prd; + struct bgp_static *bgp_static; + u_int32_t label; + char buf[SU_ADDRSTRLEN]; + char rdbuf[RD_ADDRSTRLEN]; + + /* Network configuration. */ + for (prn = bgp_table_top (bgp->route[afi][safi]); prn; prn = bgp_route_next (prn)) + if ((table = prn->info) != NULL) + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + if ((bgp_static = rn->info) != NULL) + { + p = &rn->p; + prd = (struct prefix_rd *) &prn->p; + + /* "address-family" display. */ + bgp_config_write_family_header (vty, afi, safi, write); + + /* "network" configuration display. */ + prefix_rd2str (prd, rdbuf, RD_ADDRSTRLEN); + label = decode_label (bgp_static->tag); + + vty_out (vty, " network %s/%d rd %s tag %d", + inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen, + rdbuf, label); + vty_out (vty, "%s", VTY_NEWLINE); + } + return 0; +} + +/* Configuration of static route announcement and aggregate + information. */ +int +bgp_config_write_network (struct vty *vty, struct bgp *bgp, + afi_t afi, safi_t safi, int *write) +{ + struct bgp_node *rn; + struct prefix *p; + struct bgp_static *bgp_static; + struct bgp_aggregate *bgp_aggregate; + char buf[SU_ADDRSTRLEN]; + + if (afi == AFI_IP && safi == SAFI_MPLS_VPN) + return bgp_config_write_network_vpnv4 (vty, bgp, afi, safi, write); + + /* Network configuration. */ + for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) + if ((bgp_static = rn->info) != NULL) + { + p = &rn->p; + + /* "address-family" display. */ + bgp_config_write_family_header (vty, afi, safi, write); + + /* "network" configuration display. */ + if (bgp_option_check (BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) + { + u_int32_t destination; + struct in_addr netmask; + + destination = ntohl (p->u.prefix4.s_addr); + masklen2ip (p->prefixlen, &netmask); + vty_out (vty, " network %s", + inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN)); + + if ((IN_CLASSC (destination) && p->prefixlen == 24) + || (IN_CLASSB (destination) && p->prefixlen == 16) + || (IN_CLASSA (destination) && p->prefixlen == 8) + || p->u.prefix4.s_addr == 0) + { + /* Natural mask is not display. */ + } + else + vty_out (vty, " mask %s", inet_ntoa (netmask)); + } + else + { + vty_out (vty, " network %s/%d", + inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); + } + + if (bgp_static->rmap.name) + vty_out (vty, " route-map %s", bgp_static->rmap.name); + else if (bgp_static->backdoor) + vty_out (vty, " backdoor"); + + vty_out (vty, "%s", VTY_NEWLINE); + } + + /* Aggregate-address configuration. */ + for (rn = bgp_table_top (bgp->aggregate[afi][safi]); rn; rn = bgp_route_next (rn)) + if ((bgp_aggregate = rn->info) != NULL) + { + p = &rn->p; + + /* "address-family" display. */ + bgp_config_write_family_header (vty, afi, safi, write); + + if (bgp_option_check (BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) + { + struct in_addr netmask; + + masklen2ip (p->prefixlen, &netmask); + vty_out (vty, " aggregate-address %s %s", + inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + inet_ntoa (netmask)); + } + else + { + vty_out (vty, " aggregate-address %s/%d", + inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); + } + + if (bgp_aggregate->as_set) + vty_out (vty, " as-set"); + + if (bgp_aggregate->summary_only) + vty_out (vty, " summary-only"); + + vty_out (vty, "%s", VTY_NEWLINE); + } + + return 0; +} + +int +bgp_config_write_distance (struct vty *vty, struct bgp *bgp) +{ + struct bgp_node *rn; + struct bgp_distance *bdistance; + + /* Distance configuration. */ + if (bgp->distance_ebgp + && bgp->distance_ibgp + && bgp->distance_local + && (bgp->distance_ebgp != ZEBRA_EBGP_DISTANCE_DEFAULT + || bgp->distance_ibgp != ZEBRA_IBGP_DISTANCE_DEFAULT + || bgp->distance_local != ZEBRA_IBGP_DISTANCE_DEFAULT)) + vty_out (vty, " distance bgp %d %d %d%s", + bgp->distance_ebgp, bgp->distance_ibgp, bgp->distance_local, + VTY_NEWLINE); + + for (rn = bgp_table_top (bgp_distance_table); rn; rn = bgp_route_next (rn)) + if ((bdistance = rn->info) != NULL) + { + vty_out (vty, " distance %d %s/%d %s%s", bdistance->distance, + inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen, + bdistance->access_list ? bdistance->access_list : "", + VTY_NEWLINE); + } + + return 0; +} + +/* Allocate routing table structure and install commands. */ +void +bgp_route_init () +{ + /* Init BGP distance table. */ + bgp_distance_table = bgp_table_init (); + + /* IPv4 BGP commands. */ + install_element (BGP_NODE, &bgp_network_cmd); + install_element (BGP_NODE, &bgp_network_mask_cmd); + install_element (BGP_NODE, &bgp_network_mask_natural_cmd); + install_element (BGP_NODE, &bgp_network_route_map_cmd); + install_element (BGP_NODE, &bgp_network_mask_route_map_cmd); + install_element (BGP_NODE, &bgp_network_mask_natural_route_map_cmd); + install_element (BGP_NODE, &bgp_network_backdoor_cmd); + install_element (BGP_NODE, &bgp_network_mask_backdoor_cmd); + install_element (BGP_NODE, &bgp_network_mask_natural_backdoor_cmd); + install_element (BGP_NODE, &no_bgp_network_cmd); + install_element (BGP_NODE, &no_bgp_network_mask_cmd); + install_element (BGP_NODE, &no_bgp_network_mask_natural_cmd); + install_element (BGP_NODE, &no_bgp_network_route_map_cmd); + install_element (BGP_NODE, &no_bgp_network_mask_route_map_cmd); + install_element (BGP_NODE, &no_bgp_network_mask_natural_route_map_cmd); + install_element (BGP_NODE, &no_bgp_network_backdoor_cmd); + install_element (BGP_NODE, &no_bgp_network_mask_backdoor_cmd); + install_element (BGP_NODE, &no_bgp_network_mask_natural_backdoor_cmd); + + install_element (BGP_NODE, &aggregate_address_cmd); + install_element (BGP_NODE, &aggregate_address_mask_cmd); + install_element (BGP_NODE, &aggregate_address_summary_only_cmd); + install_element (BGP_NODE, &aggregate_address_mask_summary_only_cmd); + install_element (BGP_NODE, &aggregate_address_as_set_cmd); + install_element (BGP_NODE, &aggregate_address_mask_as_set_cmd); + install_element (BGP_NODE, &aggregate_address_as_set_summary_cmd); + install_element (BGP_NODE, &aggregate_address_mask_as_set_summary_cmd); + install_element (BGP_NODE, &aggregate_address_summary_as_set_cmd); + install_element (BGP_NODE, &aggregate_address_mask_summary_as_set_cmd); + install_element (BGP_NODE, &no_aggregate_address_cmd); + install_element (BGP_NODE, &no_aggregate_address_summary_only_cmd); + install_element (BGP_NODE, &no_aggregate_address_as_set_cmd); + install_element (BGP_NODE, &no_aggregate_address_as_set_summary_cmd); + install_element (BGP_NODE, &no_aggregate_address_summary_as_set_cmd); + install_element (BGP_NODE, &no_aggregate_address_mask_cmd); + install_element (BGP_NODE, &no_aggregate_address_mask_summary_only_cmd); + install_element (BGP_NODE, &no_aggregate_address_mask_as_set_cmd); + install_element (BGP_NODE, &no_aggregate_address_mask_as_set_summary_cmd); + install_element (BGP_NODE, &no_aggregate_address_mask_summary_as_set_cmd); + + /* IPv4 unicast configuration. */ + install_element (BGP_IPV4_NODE, &bgp_network_cmd); + install_element (BGP_IPV4_NODE, &bgp_network_mask_cmd); + install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_cmd); + install_element (BGP_IPV4_NODE, &bgp_network_route_map_cmd); + install_element (BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd); + install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_network_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_network_mask_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_network_route_map_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_network_mask_route_map_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_route_map_cmd); + install_element (BGP_IPV4_NODE, &aggregate_address_cmd); + install_element (BGP_IPV4_NODE, &aggregate_address_mask_cmd); + install_element (BGP_IPV4_NODE, &aggregate_address_summary_only_cmd); + install_element (BGP_IPV4_NODE, &aggregate_address_mask_summary_only_cmd); + install_element (BGP_IPV4_NODE, &aggregate_address_as_set_cmd); + install_element (BGP_IPV4_NODE, &aggregate_address_mask_as_set_cmd); + install_element (BGP_IPV4_NODE, &aggregate_address_as_set_summary_cmd); + install_element (BGP_IPV4_NODE, &aggregate_address_mask_as_set_summary_cmd); + install_element (BGP_IPV4_NODE, &aggregate_address_summary_as_set_cmd); + install_element (BGP_IPV4_NODE, &aggregate_address_mask_summary_as_set_cmd); + install_element (BGP_IPV4_NODE, &no_aggregate_address_cmd); + install_element (BGP_IPV4_NODE, &no_aggregate_address_summary_only_cmd); + install_element (BGP_IPV4_NODE, &no_aggregate_address_as_set_cmd); + install_element (BGP_IPV4_NODE, &no_aggregate_address_as_set_summary_cmd); + install_element (BGP_IPV4_NODE, &no_aggregate_address_summary_as_set_cmd); + install_element (BGP_IPV4_NODE, &no_aggregate_address_mask_cmd); + install_element (BGP_IPV4_NODE, &no_aggregate_address_mask_summary_only_cmd); + install_element (BGP_IPV4_NODE, &no_aggregate_address_mask_as_set_cmd); + install_element (BGP_IPV4_NODE, &no_aggregate_address_mask_as_set_summary_cmd); + install_element (BGP_IPV4_NODE, &no_aggregate_address_mask_summary_as_set_cmd); + + /* IPv4 multicast configuration. */ + install_element (BGP_IPV4M_NODE, &bgp_network_cmd); + install_element (BGP_IPV4M_NODE, &bgp_network_mask_cmd); + install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_cmd); + install_element (BGP_IPV4M_NODE, &bgp_network_route_map_cmd); + install_element (BGP_IPV4M_NODE, &bgp_network_mask_route_map_cmd); + install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_route_map_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_network_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_network_route_map_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_route_map_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_route_map_cmd); + install_element (BGP_IPV4M_NODE, &aggregate_address_cmd); + install_element (BGP_IPV4M_NODE, &aggregate_address_mask_cmd); + install_element (BGP_IPV4M_NODE, &aggregate_address_summary_only_cmd); + install_element (BGP_IPV4M_NODE, &aggregate_address_mask_summary_only_cmd); + install_element (BGP_IPV4M_NODE, &aggregate_address_as_set_cmd); + install_element (BGP_IPV4M_NODE, &aggregate_address_mask_as_set_cmd); + install_element (BGP_IPV4M_NODE, &aggregate_address_as_set_summary_cmd); + install_element (BGP_IPV4M_NODE, &aggregate_address_mask_as_set_summary_cmd); + install_element (BGP_IPV4M_NODE, &aggregate_address_summary_as_set_cmd); + install_element (BGP_IPV4M_NODE, &aggregate_address_mask_summary_as_set_cmd); + install_element (BGP_IPV4M_NODE, &no_aggregate_address_cmd); + install_element (BGP_IPV4M_NODE, &no_aggregate_address_summary_only_cmd); + install_element (BGP_IPV4M_NODE, &no_aggregate_address_as_set_cmd); + install_element (BGP_IPV4M_NODE, &no_aggregate_address_as_set_summary_cmd); + install_element (BGP_IPV4M_NODE, &no_aggregate_address_summary_as_set_cmd); + install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd); + install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_summary_only_cmd); + install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_as_set_cmd); + install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_as_set_summary_cmd); + install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_summary_as_set_cmd); + + install_element (VIEW_NODE, &show_ip_bgp_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_cmd); + install_element (VIEW_NODE, &show_ip_bgp_route_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_route_cmd); + install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_route_cmd); + install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_route_cmd); + install_element (VIEW_NODE, &show_ip_bgp_prefix_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_cmd); + install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd); + install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd); + install_element (VIEW_NODE, &show_ip_bgp_view_cmd); + install_element (VIEW_NODE, &show_ip_bgp_view_route_cmd); + install_element (VIEW_NODE, &show_ip_bgp_view_prefix_cmd); + install_element (VIEW_NODE, &show_ip_bgp_regexp_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_regexp_cmd); + install_element (VIEW_NODE, &show_ip_bgp_prefix_list_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_list_cmd); + install_element (VIEW_NODE, &show_ip_bgp_filter_list_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_filter_list_cmd); + install_element (VIEW_NODE, &show_ip_bgp_route_map_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_route_map_cmd); + install_element (VIEW_NODE, &show_ip_bgp_cidr_only_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_cidr_only_cmd); + install_element (VIEW_NODE, &show_ip_bgp_community_all_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_community_all_cmd); + install_element (VIEW_NODE, &show_ip_bgp_community_cmd); + install_element (VIEW_NODE, &show_ip_bgp_community2_cmd); + install_element (VIEW_NODE, &show_ip_bgp_community3_cmd); + install_element (VIEW_NODE, &show_ip_bgp_community4_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_community_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_community2_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_community3_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_community4_cmd); + install_element (VIEW_NODE, &show_ip_bgp_community_exact_cmd); + install_element (VIEW_NODE, &show_ip_bgp_community2_exact_cmd); + install_element (VIEW_NODE, &show_ip_bgp_community3_exact_cmd); + install_element (VIEW_NODE, &show_ip_bgp_community4_exact_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_community_exact_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_community2_exact_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_community3_exact_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_community4_exact_cmd); + install_element (VIEW_NODE, &show_ip_bgp_community_list_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_community_list_cmd); + install_element (VIEW_NODE, &show_ip_bgp_community_list_exact_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_community_list_exact_cmd); + install_element (VIEW_NODE, &show_ip_bgp_prefix_longer_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_longer_cmd); + install_element (VIEW_NODE, &show_ip_bgp_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd); + install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd); + install_element (VIEW_NODE, &show_ip_bgp_dampened_paths_cmd); + install_element (VIEW_NODE, &show_ip_bgp_flap_statistics_cmd); + install_element (VIEW_NODE, &show_ip_bgp_flap_address_cmd); + install_element (VIEW_NODE, &show_ip_bgp_flap_prefix_cmd); + install_element (VIEW_NODE, &show_ip_bgp_flap_cidr_only_cmd); + install_element (VIEW_NODE, &show_ip_bgp_flap_regexp_cmd); + install_element (VIEW_NODE, &show_ip_bgp_flap_filter_list_cmd); + install_element (VIEW_NODE, &show_ip_bgp_flap_prefix_list_cmd); + install_element (VIEW_NODE, &show_ip_bgp_flap_prefix_longer_cmd); + install_element (VIEW_NODE, &show_ip_bgp_flap_route_map_cmd); + install_element (VIEW_NODE, &show_ip_bgp_neighbor_flap_cmd); + install_element (VIEW_NODE, &show_ip_bgp_neighbor_damp_cmd); + + install_element (ENABLE_NODE, &show_ip_bgp_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_route_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_route_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_route_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_route_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_prefix_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_view_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_view_route_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_view_prefix_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_regexp_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_regexp_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_prefix_list_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_list_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_filter_list_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_filter_list_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_route_map_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_route_map_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_cidr_only_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_cidr_only_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_community_all_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community_all_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_community_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_community2_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_community3_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_community4_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community2_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community3_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community4_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_community_exact_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_community2_exact_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_community3_exact_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_community4_exact_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community_exact_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community2_exact_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community3_exact_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community4_exact_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_community_list_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community_list_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_community_list_exact_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community_list_exact_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_prefix_longer_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_longer_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_routes_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_routes_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_neighbor_routes_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_dampened_paths_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_flap_statistics_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_flap_address_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_flap_prefix_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_flap_cidr_only_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_flap_regexp_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_flap_filter_list_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_flap_prefix_list_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_flap_prefix_longer_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_flap_route_map_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_neighbor_flap_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_neighbor_damp_cmd); + + /* BGP dampening clear commands */ + install_element (ENABLE_NODE, &clear_ip_bgp_dampening_cmd); + install_element (ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd); + install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd); + install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd); + +#ifdef HAVE_IPV6 + /* New config IPv6 BGP commands. */ + install_element (BGP_IPV6_NODE, &ipv6_bgp_network_cmd); + install_element (BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd); + install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd); + install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_route_map_cmd); + + install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_cmd); + install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_summary_only_cmd); + install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd); + install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_summary_only_cmd); + + /* Old config IPv6 BGP commands. */ + install_element (BGP_NODE, &old_ipv6_bgp_network_cmd); + install_element (BGP_NODE, &old_no_ipv6_bgp_network_cmd); + + install_element (BGP_NODE, &old_ipv6_aggregate_address_cmd); + install_element (BGP_NODE, &old_ipv6_aggregate_address_summary_only_cmd); + install_element (BGP_NODE, &old_no_ipv6_aggregate_address_cmd); + install_element (BGP_NODE, &old_no_ipv6_aggregate_address_summary_only_cmd); + + install_element (VIEW_NODE, &show_bgp_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_cmd); + install_element (VIEW_NODE, &show_bgp_route_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_route_cmd); + install_element (VIEW_NODE, &show_bgp_prefix_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_prefix_cmd); + install_element (VIEW_NODE, &show_bgp_regexp_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_regexp_cmd); + install_element (VIEW_NODE, &show_bgp_prefix_list_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_prefix_list_cmd); + install_element (VIEW_NODE, &show_bgp_filter_list_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_filter_list_cmd); + install_element (VIEW_NODE, &show_bgp_route_map_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_route_map_cmd); + install_element (VIEW_NODE, &show_bgp_community_all_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_community_all_cmd); + install_element (VIEW_NODE, &show_bgp_community_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_community_cmd); + install_element (VIEW_NODE, &show_bgp_community2_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_community2_cmd); + install_element (VIEW_NODE, &show_bgp_community3_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_community3_cmd); + install_element (VIEW_NODE, &show_bgp_community4_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_community4_cmd); + install_element (VIEW_NODE, &show_bgp_community_exact_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_community_exact_cmd); + install_element (VIEW_NODE, &show_bgp_community2_exact_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_community2_exact_cmd); + install_element (VIEW_NODE, &show_bgp_community3_exact_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_community3_exact_cmd); + install_element (VIEW_NODE, &show_bgp_community4_exact_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_community4_exact_cmd); + install_element (VIEW_NODE, &show_bgp_community_list_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_community_list_cmd); + install_element (VIEW_NODE, &show_bgp_community_list_exact_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_community_list_exact_cmd); + install_element (VIEW_NODE, &show_bgp_prefix_longer_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_prefix_longer_cmd); + install_element (VIEW_NODE, &show_bgp_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_bgp_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &show_bgp_neighbor_routes_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_routes_cmd); + install_element (VIEW_NODE, &show_bgp_neighbor_received_prefix_filter_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_received_prefix_filter_cmd); + + install_element (ENABLE_NODE, &show_bgp_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_cmd); + install_element (ENABLE_NODE, &show_bgp_route_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_route_cmd); + install_element (ENABLE_NODE, &show_bgp_prefix_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_prefix_cmd); + install_element (ENABLE_NODE, &show_bgp_regexp_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_regexp_cmd); + install_element (ENABLE_NODE, &show_bgp_prefix_list_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_prefix_list_cmd); + install_element (ENABLE_NODE, &show_bgp_filter_list_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_filter_list_cmd); + install_element (ENABLE_NODE, &show_bgp_route_map_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_route_map_cmd); + install_element (ENABLE_NODE, &show_bgp_community_all_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_community_all_cmd); + install_element (ENABLE_NODE, &show_bgp_community_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_community_cmd); + install_element (ENABLE_NODE, &show_bgp_community2_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_community2_cmd); + install_element (ENABLE_NODE, &show_bgp_community3_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_community3_cmd); + install_element (ENABLE_NODE, &show_bgp_community4_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_community4_cmd); + install_element (ENABLE_NODE, &show_bgp_community_exact_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_community_exact_cmd); + install_element (ENABLE_NODE, &show_bgp_community2_exact_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_community2_exact_cmd); + install_element (ENABLE_NODE, &show_bgp_community3_exact_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_community3_exact_cmd); + install_element (ENABLE_NODE, &show_bgp_community4_exact_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_community4_exact_cmd); + install_element (ENABLE_NODE, &show_bgp_community_list_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_community_list_cmd); + install_element (ENABLE_NODE, &show_bgp_community_list_exact_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_community_list_exact_cmd); + install_element (ENABLE_NODE, &show_bgp_prefix_longer_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_prefix_longer_cmd); + install_element (ENABLE_NODE, &show_bgp_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &show_bgp_neighbor_received_routes_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_received_routes_cmd); + install_element (ENABLE_NODE, &show_bgp_neighbor_routes_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_routes_cmd); + install_element (ENABLE_NODE, &show_bgp_neighbor_received_prefix_filter_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_received_prefix_filter_cmd); + + /* old command */ + install_element (VIEW_NODE, &show_ipv6_bgp_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_route_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_prefix_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_regexp_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_prefix_list_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_filter_list_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_community_all_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_community_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_community2_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_community3_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_community4_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_community_exact_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_community2_exact_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_community3_exact_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_community4_exact_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_community_list_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_community_list_exact_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_prefix_longer_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_route_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_prefix_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_regexp_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_prefix_list_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_filter_list_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_community_all_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_community_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_community2_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_community3_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_community4_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_community_exact_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_community2_exact_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_community3_exact_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_community4_exact_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_community_list_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_community_list_exact_cmd); + install_element (VIEW_NODE, &show_ipv6_mbgp_prefix_longer_cmd); + + /* old command */ + install_element (ENABLE_NODE, &show_ipv6_bgp_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_route_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_prefix_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_regexp_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_prefix_list_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_filter_list_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_community_all_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_community_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_community2_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_community3_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_community4_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_community_exact_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_community2_exact_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_community3_exact_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_community4_exact_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_community_list_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_community_list_exact_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_prefix_longer_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_route_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_prefix_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_regexp_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_prefix_list_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_filter_list_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_community_all_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_community_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_community2_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_community3_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_community4_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_community_exact_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_community2_exact_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_community3_exact_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_community4_exact_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_community_list_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_community_list_exact_cmd); + install_element (ENABLE_NODE, &show_ipv6_mbgp_prefix_longer_cmd); + + /* old command */ + install_element (VIEW_NODE, &ipv6_bgp_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &ipv6_bgp_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &ipv6_mbgp_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &ipv6_mbgp_neighbor_advertised_route_cmd); + + /* old command */ + install_element (VIEW_NODE, &ipv6_bgp_neighbor_received_routes_cmd); + install_element (ENABLE_NODE, &ipv6_bgp_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &ipv6_mbgp_neighbor_received_routes_cmd); + install_element (ENABLE_NODE, &ipv6_mbgp_neighbor_received_routes_cmd); + + /* old command */ + install_element (VIEW_NODE, &ipv6_bgp_neighbor_routes_cmd); + install_element (ENABLE_NODE, &ipv6_bgp_neighbor_routes_cmd); + install_element (VIEW_NODE, &ipv6_mbgp_neighbor_routes_cmd); + install_element (ENABLE_NODE, &ipv6_mbgp_neighbor_routes_cmd); +#endif /* HAVE_IPV6 */ + + install_element (BGP_NODE, &bgp_distance_cmd); + install_element (BGP_NODE, &no_bgp_distance_cmd); + install_element (BGP_NODE, &no_bgp_distance2_cmd); + install_element (BGP_NODE, &bgp_distance_source_cmd); + install_element (BGP_NODE, &no_bgp_distance_source_cmd); + install_element (BGP_NODE, &bgp_distance_source_access_list_cmd); + install_element (BGP_NODE, &no_bgp_distance_source_access_list_cmd); + + install_element (BGP_NODE, &bgp_damp_set_cmd); + install_element (BGP_NODE, &bgp_damp_set2_cmd); + install_element (BGP_NODE, &bgp_damp_set3_cmd); + install_element (BGP_NODE, &bgp_damp_unset_cmd); + install_element (BGP_NODE, &bgp_damp_unset2_cmd); + install_element (BGP_IPV4_NODE, &bgp_damp_set_cmd); + install_element (BGP_IPV4_NODE, &bgp_damp_set2_cmd); + install_element (BGP_IPV4_NODE, &bgp_damp_set3_cmd); + install_element (BGP_IPV4_NODE, &bgp_damp_unset_cmd); + install_element (BGP_IPV4_NODE, &bgp_damp_unset2_cmd); +} -- cgit v1.2.1