summaryrefslogtreecommitdiff
path: root/bgpd
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_advertise.c10
-rw-r--r--bgpd/bgp_aspath.c167
-rw-r--r--bgpd/bgp_aspath.h4
-rw-r--r--bgpd/bgp_attr.c763
-rw-r--r--bgpd/bgp_attr.h14
-rw-r--r--bgpd/bgp_clist.c4
-rw-r--r--bgpd/bgp_community.c13
-rw-r--r--bgpd/bgp_community.h2
-rw-r--r--bgpd/bgp_ecommunity.c33
-rw-r--r--bgpd/bgp_ecommunity.h4
-rw-r--r--bgpd/bgp_main.c10
-rw-r--r--bgpd/bgp_network.c20
-rw-r--r--bgpd/bgp_nexthop.c22
-rw-r--r--bgpd/bgp_packet.c158
-rw-r--r--bgpd/bgp_route.c1088
-rw-r--r--bgpd/bgp_routemap.c34
-rw-r--r--bgpd/bgp_table.c1
-rw-r--r--bgpd/bgp_vty.c219
-rw-r--r--bgpd/bgp_zebra.c8
-rw-r--r--bgpd/bgpd.c177
-rw-r--r--bgpd/bgpd.h8
21 files changed, 2064 insertions, 695 deletions
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c
index 87eb7ac7..666218fa 100644
--- a/bgpd/bgp_advertise.c
+++ b/bgpd/bgp_advertise.c
@@ -140,13 +140,13 @@ bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
baa->refcnt--;
if (baa->refcnt && baa->attr)
- bgp_attr_unintern (baa->attr);
+ bgp_attr_unintern (&baa->attr);
else
{
if (baa->attr)
{
hash_release (hash, baa);
- bgp_attr_unintern (baa->attr);
+ bgp_attr_unintern (&baa->attr);
}
baa_free (baa);
}
@@ -319,7 +319,7 @@ bgp_adj_out_remove (struct bgp_node *rn, struct bgp_adj_out *adj,
struct peer *peer, afi_t afi, safi_t safi)
{
if (adj->attr)
- bgp_attr_unintern (adj->attr);
+ bgp_attr_unintern (&adj->attr);
if (adj->adv)
bgp_advertise_clean (peer, adj, afi, safi);
@@ -339,7 +339,7 @@ bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
{
if (adj->attr != attr)
{
- bgp_attr_unintern (adj->attr);
+ bgp_attr_unintern (&adj->attr);
adj->attr = bgp_attr_intern (attr);
}
return;
@@ -355,7 +355,7 @@ bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
void
bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
{
- bgp_attr_unintern (bai->attr);
+ bgp_attr_unintern (&bai->attr);
BGP_ADJ_IN_DEL (rn, bai);
peer_unlock (bai->peer); /* adj_in peer reference */
XFREE (MTYPE_BGP_ADJ_IN, bai);
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 5a73eeff..776c7127 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -91,13 +91,13 @@ static struct hash *ashash;
/* Stream for SNMP. See aspath_snmp_pathseg */
static struct stream *snmp_stream;
-static inline as_t *
+static as_t *
assegment_data_new (int num)
{
return (XCALLOC (MTYPE_AS_SEG_DATA, ASSEGMENT_DATA_SIZE (num, 1)));
}
-static inline void
+static void
assegment_data_free (as_t *asdata)
{
XFREE (MTYPE_AS_SEG_DATA,asdata);
@@ -340,19 +340,21 @@ aspath_free (struct aspath *aspath)
/* Unintern aspath from AS path bucket. */
void
-aspath_unintern (struct aspath *aspath)
+aspath_unintern (struct aspath **aspath)
{
struct aspath *ret;
+ struct aspath *asp = *aspath;
+
+ if (asp->refcnt)
+ asp->refcnt--;
- if (aspath->refcnt)
- aspath->refcnt--;
-
- if (aspath->refcnt == 0)
+ if (asp->refcnt == 0)
{
/* This aspath must exist in aspath hash table. */
- ret = hash_release (ashash, aspath);
+ ret = hash_release (ashash, asp);
assert (ret != NULL);
- aspath_free (aspath);
+ aspath_free (asp);
+ *aspath = NULL;
}
}
@@ -671,78 +673,78 @@ aspath_hash_alloc (void *arg)
return aspath;
}
-/* parse as-segment byte stream in struct assegment
- *
- * Returns NULL if the AS_PATH or AS4_PATH is not valid.
- */
-static struct assegment *
-assegments_parse (struct stream *s, size_t length, int use32bit, int as4_path)
+/* parse as-segment byte stream in struct assegment */
+static int
+assegments_parse (struct stream *s, size_t length,
+ struct assegment **result, int use32bit)
{
struct assegment_header segh;
struct assegment *seg, *prev = NULL, *head = NULL;
+ size_t bytes = 0;
- assert (length > 0); /* does not expect empty AS_PATH or AS4_PATH */
+ /* empty aspath (ie iBGP or somesuch) */
+ if (length == 0)
+ return 0;
if (BGP_DEBUG (as4, AS4_SEGMENT))
zlog_debug ("[AS4SEG] Parse aspath segment: got total byte length %lu",
(unsigned long) length);
-
- /* double check that length does not exceed stream */
- if (STREAM_READABLE(s) < length)
- return NULL;
+ /* basic checks */
+ if ((STREAM_READABLE(s) < length)
+ || (STREAM_READABLE(s) < AS_HEADER_SIZE)
+ || (length % AS16_VALUE_SIZE ))
+ return -1;
- /* deal with each segment in turn */
- while (length > 0)
+ while (bytes < length)
{
int i;
size_t seg_size;
- /* softly softly, get the header first on its own */
- if (length >= AS_HEADER_SIZE)
+ if ((length - bytes) <= AS_HEADER_SIZE)
{
+ if (head)
+ assegment_free_all (head);
+ return -1;
+ }
+
+ /* softly softly, get the header first on its own */
segh.type = stream_getc (s);
segh.length = stream_getc (s);
seg_size = ASSEGMENT_SIZE(segh.length, use32bit);
- /* includes the header bytes */
if (BGP_DEBUG (as4, AS4_SEGMENT))
zlog_debug ("[AS4SEG] Parse aspath segment: got type %d, length %d",
segh.type, segh.length);
- switch (segh.type)
- {
- case AS_SEQUENCE:
- case AS_SET:
- break ;
-
- case AS_CONFED_SEQUENCE:
- case AS_CONFED_SET:
- if (!as4_path)
- break ;
- /* RFC4893 3: "invalid for the AS4_PATH attribute" */
- /* fall through */
-
- default: /* reject unknown or invalid AS_PATH segment types */
- seg_size = 0 ;
- } ;
- }
- else
- seg_size = 0 ;
-
- /* Stop now if segment is not valid (discarding anything collected to date)
- *
- * RFC4271 4.3, Path Attributes, b) AS_PATH:
- *
- * "path segment value field contains one or more AS numbers"
+ /* check it.. */
+ if ( ((bytes + seg_size) > length)
+ /* 1771bis 4.3b: seg length contains one or more */
+ || (segh.length == 0)
+ /* Paranoia in case someone changes type of segment length.
+ * Shift both values by 0x10 to make the comparison operate
+ * on more, than 8 bits (otherwise it's a warning, bug #564).
*/
- if ((seg_size == 0) || (seg_size > length) || (segh.length == 0))
+ || ((sizeof segh.length > 1)
+ && (0x10 + segh.length > 0x10 + AS_SEGMENT_MAX)))
{
+ if (head)
assegment_free_all (head);
- return NULL;
+ return -1;
}
- length -= seg_size ;
+ switch (segh.type)
+ {
+ case AS_SEQUENCE:
+ case AS_SET:
+ case AS_CONFED_SEQUENCE:
+ case AS_CONFED_SET:
+ break;
+ default:
+ if (head)
+ assegment_free_all (head);
+ return -1;
+ }
/* now its safe to trust lengths */
seg = assegment_new (segh.type, segh.length);
@@ -755,52 +757,47 @@ assegments_parse (struct stream *s, size_t length, int use32bit, int as4_path)
for (i = 0; i < segh.length; i++)
seg->as[i] = (use32bit) ? stream_getl (s) : stream_getw (s);
+ bytes += seg_size;
+
if (BGP_DEBUG (as4, AS4_SEGMENT))
- zlog_debug ("[AS4SEG] Parse aspath segment: length left: %lu",
- (unsigned long) length);
+ zlog_debug ("[AS4SEG] Parse aspath segment: Bytes now: %lu",
+ (unsigned long) bytes);
prev = seg;
}
- return assegment_normalise (head);
+ *result = assegment_normalise (head);
+ return 0;
}
-/* AS path parse function -- parses AS_PATH and AS4_PATH attributes
- *
- * Requires: s -- stream, currently positioned before first segment
- * of AS_PATH or AS4_PATH (ie after attribute header)
- * length -- length of the value of the AS_PATH or AS4_PATH
- * use32bit -- true <=> 4Byte ASN, otherwise 2Byte ASN
- * as4_path -- true <=> AS4_PATH, otherwise AS_PATH
- *
- * Returns: if valid: address of struct aspath in the hash of known aspaths,
- * with reference count incremented.
- * else: NULL
- *
- * NB: empty AS path (length == 0) is valid. The returned struct aspath will
- * have segments == NULL and str == zero length string (unique).
+/* AS path parse function. pnt is a pointer to byte stream and length
+ is length of byte stream. If there is same AS path in the the AS
+ path hash then return it else make new AS path structure.
+
+ On error NULL is returned.
*/
struct aspath *
-aspath_parse (struct stream *s, size_t length, int use32bit, int as4_path)
+aspath_parse (struct stream *s, size_t length, int use32bit)
{
struct aspath as;
struct aspath *find;
- /* Parse each segment and construct normalised list of struct assegment */
- memset (&as, 0, sizeof (struct aspath));
- if (length != 0)
- {
- as.segments = assegments_parse (s, length, use32bit, as4_path);
+ /* If length is odd it's malformed AS path. */
+ /* Nit-picking: if (use32bit == 0) it is malformed if odd,
+ * otherwise its malformed when length is larger than 2 and (length-2)
+ * is not dividable by 4.
+ * But... this time we're lazy
+ */
+ if (length % AS16_VALUE_SIZE )
+ return NULL;
- if (as.segments == NULL)
- return NULL ; /* Invalid AS_PATH or AS4_PATH */
- } ;
+ memset (&as, 0, sizeof (struct aspath));
+ if (assegments_parse (s, length, &as.segments, use32bit) < 0)
+ return NULL;
/* If already same aspath exist then return it. */
find = hash_get (ashash, &as, aspath_hash_alloc);
- assert(find) ; /* valid aspath, so must find or create */
-
/* aspath_hash_alloc dupes segments too. that probably could be
* optimised out.
*/
@@ -808,12 +805,14 @@ aspath_parse (struct stream *s, size_t length, int use32bit, int as4_path)
if (as.str)
XFREE (MTYPE_AS_STR, as.str);
+ if (! find)
+ return NULL;
find->refcnt++;
return find;
}
-static inline void
+static void
assegment_data_put (struct stream *s, as_t *as, int num, int use32bit)
{
int i;
@@ -831,7 +830,7 @@ assegment_data_put (struct stream *s, as_t *as, int num, int use32bit)
}
}
-static inline size_t
+static size_t
assegment_header_put (struct stream *s, u_char type, int length)
{
size_t lenp;
@@ -1631,7 +1630,7 @@ aspath_segment_add (struct aspath *as, int type)
struct aspath *
aspath_empty (void)
{
- return aspath_parse (NULL, 0, 1, 0); /* 32Bit ;-) not AS4_PATH */
+ return aspath_parse (NULL, 0, 1); /* 32Bit ;-) */
}
struct aspath *
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index d63b914c..d55f9ce6 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -65,7 +65,7 @@ struct aspath
/* Prototypes. */
extern void aspath_init (void);
extern void aspath_finish (void);
-extern struct aspath *aspath_parse (struct stream *, size_t, int, int);
+extern struct aspath *aspath_parse (struct stream *, size_t, int);
extern struct aspath *aspath_dup (struct aspath *);
extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *);
extern struct aspath *aspath_prepend (struct aspath *, struct aspath *);
@@ -80,7 +80,7 @@ extern struct aspath *aspath_empty_get (void);
extern struct aspath *aspath_str2aspath (const char *);
extern void aspath_free (struct aspath *);
extern struct aspath *aspath_intern (struct aspath *);
-extern void aspath_unintern (struct aspath *);
+extern void aspath_unintern (struct aspath **);
extern const char *aspath_print (struct aspath *);
extern void aspath_print_vty (struct vty *, const char *, struct aspath *, const char *);
extern void aspath_print_all_vty (struct vty *);
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 2205e267..92c1a09f 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -28,6 +28,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "stream.h"
#include "log.h"
#include "hash.h"
+#include "jhash.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_attr.h"
@@ -127,18 +128,9 @@ cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
static unsigned int
cluster_hash_key_make (void *p)
{
- struct cluster_list * cluster = (struct cluster_list *) p;
- unsigned int key = 0;
- int length;
- caddr_t pnt;
+ const struct cluster_list *cluster = p;
- length = cluster->length;
- pnt = (caddr_t) cluster->list;
-
- while (length)
- key += pnt[--length];
-
- return key;
+ return jhash(cluster->list, cluster->length, 0);
}
static int
@@ -194,14 +186,12 @@ cluster_intern (struct cluster_list *cluster)
void
cluster_unintern (struct cluster_list *cluster)
{
- struct cluster_list *ret;
-
if (cluster->refcnt)
cluster->refcnt--;
if (cluster->refcnt == 0)
{
- ret = hash_release (cluster_hash, cluster);
+ hash_release (cluster_hash, cluster);
cluster_free (cluster);
}
}
@@ -254,14 +244,12 @@ transit_intern (struct transit *transit)
void
transit_unintern (struct transit *transit)
{
- struct transit *ret;
-
if (transit->refcnt)
transit->refcnt--;
if (transit->refcnt == 0)
{
- ret = hash_release (transit_hash, transit);
+ hash_release (transit_hash, transit);
transit_free (transit);
}
}
@@ -269,18 +257,9 @@ transit_unintern (struct transit *transit)
static unsigned int
transit_hash_key_make (void *p)
{
- struct transit * transit = (struct transit *) p;
- unsigned int key = 0;
- int length;
- caddr_t pnt;
-
- length = transit->length;
- pnt = (caddr_t) transit->val;
-
- while (length)
- key += pnt[--length];
+ const struct transit * transit = p;
- return key;
+ return jhash(transit->val, transit->length, 0);
}
static int
@@ -363,8 +342,14 @@ attr_unknown_count (void)
unsigned int
attrhash_key_make (void *p)
{
- struct attr * attr = (struct attr *) p;
- unsigned int key = 0;
+ const struct attr * attr = (struct attr *) p;
+ uint32_t key = 0;
+#define MIX(val) key = jhash_1word(val, key)
+
+ MIX(attr->origin);
+ MIX(attr->nexthop.s_addr);
+ MIX(attr->med);
+ MIX(attr->local_pref);
key += attr->origin;
key += attr->nexthop.s_addr;
@@ -373,36 +358,30 @@ attrhash_key_make (void *p)
if (attr->extra)
{
- key += attr->extra->aggregator_as;
- key += attr->extra->aggregator_addr.s_addr;
- key += attr->extra->weight;
- key += attr->extra->mp_nexthop_global_in.s_addr;
+ MIX(attr->extra->aggregator_as);
+ MIX(attr->extra->aggregator_addr.s_addr);
+ MIX(attr->extra->weight);
+ MIX(attr->extra->mp_nexthop_global_in.s_addr);
}
if (attr->aspath)
- key += aspath_key_make (attr->aspath);
+ MIX(aspath_key_make (attr->aspath));
if (attr->community)
- key += community_hash_make (attr->community);
+ MIX(community_hash_make (attr->community));
if (attr->extra)
{
if (attr->extra->ecommunity)
- key += ecommunity_hash_make (attr->extra->ecommunity);
+ MIX(ecommunity_hash_make (attr->extra->ecommunity));
if (attr->extra->cluster)
- key += cluster_hash_key_make (attr->extra->cluster);
+ MIX(cluster_hash_key_make (attr->extra->cluster));
if (attr->extra->transit)
- key += transit_hash_key_make (attr->extra->transit);
+ MIX(transit_hash_key_make (attr->extra->transit));
#ifdef HAVE_IPV6
- {
- int i;
-
- key += attr->extra->mp_nexthop_len;
- for (i = 0; i < 16; i++)
- key += attr->extra->mp_nexthop_global.s6_addr[i];
- for (i = 0; i < 16; i++)
- key += attr->extra->mp_nexthop_local.s6_addr[i];
- }
+ MIX(attr->extra->mp_nexthop_len);
+ key = jhash(attr->extra->mp_nexthop_global.s6_addr, 16, key);
+ key = jhash(attr->extra->mp_nexthop_local.s6_addr, 16, key);
#endif /* HAVE_IPV6 */
}
@@ -528,6 +507,7 @@ bgp_attr_intern (struct attr *attr)
attre->ecommunity = ecommunity_intern (attre->ecommunity);
else
attre->ecommunity->refcnt++;
+
}
if (attre->cluster)
{
@@ -544,10 +524,10 @@ bgp_attr_intern (struct attr *attr)
attre->transit->refcnt++;
}
}
-
+
find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
find->refcnt++;
-
+
return find;
}
@@ -579,17 +559,16 @@ bgp_attr_default_intern (u_char origin)
{
struct attr attr;
struct attr *new;
- struct attr_extra *attre;
memset (&attr, 0, sizeof (struct attr));
- attre = bgp_attr_extra_get (&attr);
+ bgp_attr_extra_get (&attr);
bgp_attr_default_set(&attr, origin);
new = bgp_attr_intern (&attr);
bgp_attr_extra_free (&attr);
- aspath_unintern (new->aspath);
+ aspath_unintern (&new->aspath);
return new;
}
@@ -641,52 +620,68 @@ bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
new = bgp_attr_intern (&attr);
bgp_attr_extra_free (&attr);
- aspath_unintern (new->aspath);
+ aspath_unintern (&new->aspath);
return new;
}
+/* Unintern just the sub-components of the attr, but not the attr */
+void
+bgp_attr_unintern_sub (struct attr *attr)
+{
+ /* aspath refcount shoud be decrement. */
+ if (attr->aspath)
+ aspath_unintern (&attr->aspath);
+ UNSET_FLAG(attr->flag, BGP_ATTR_AS_PATH);
+
+ if (attr->community)
+ community_unintern (&attr->community);
+ UNSET_FLAG(attr->flag, BGP_ATTR_COMMUNITIES);
+
+ if (attr->extra)
+ {
+ if (attr->extra->ecommunity)
+ ecommunity_unintern (&attr->extra->ecommunity);
+ UNSET_FLAG(attr->flag, BGP_ATTR_EXT_COMMUNITIES);
+
+ if (attr->extra->cluster)
+ cluster_unintern (attr->extra->cluster);
+ UNSET_FLAG(attr->flag, BGP_ATTR_CLUSTER_LIST);
+
+ if (attr->extra->transit)
+ transit_unintern (attr->extra->transit);
+ }
+}
+
/* Free bgp attribute and aspath. */
void
-bgp_attr_unintern (struct attr *attr)
+bgp_attr_unintern (struct attr **attr)
{
struct attr *ret;
- struct aspath *aspath;
- struct community *community;
- struct ecommunity *ecommunity = NULL;
- struct cluster_list *cluster = NULL;
- struct transit *transit = NULL;
-
+ struct attr tmp;
+
/* Decrement attribute reference. */
- attr->refcnt--;
- aspath = attr->aspath;
- community = attr->community;
- if (attr->extra)
+ (*attr)->refcnt--;
+
+ tmp = *(*attr);
+
+ if ((*attr)->extra)
{
- ecommunity = attr->extra->ecommunity;
- cluster = attr->extra->cluster;
- transit = attr->extra->transit;
+ tmp.extra = bgp_attr_extra_new ();
+ memcpy (tmp.extra, (*attr)->extra, sizeof (struct attr_extra));
}
-
+
/* If reference becomes zero then free attribute object. */
- if (attr->refcnt == 0)
+ if ((*attr)->refcnt == 0)
{
- ret = hash_release (attrhash, attr);
+ ret = hash_release (attrhash, *attr);
assert (ret != NULL);
- bgp_attr_extra_free (attr);
- XFREE (MTYPE_ATTR, attr);
+ bgp_attr_extra_free (*attr);
+ XFREE (MTYPE_ATTR, *attr);
+ *attr = NULL;
}
- /* aspath refcount shoud be decrement. */
- if (aspath)
- aspath_unintern (aspath);
- if (community)
- community_unintern (community);
- if (ecommunity)
- ecommunity_unintern (ecommunity);
- if (cluster)
- cluster_unintern (cluster);
- if (transit)
- transit_unintern (transit);
+ bgp_attr_unintern_sub (&tmp);
+ bgp_attr_extra_free (&tmp);
}
void
@@ -699,8 +694,9 @@ bgp_attr_flush (struct attr *attr)
if (attr->extra)
{
struct attr_extra *attre = attr->extra;
+
if (attre->ecommunity && ! attre->ecommunity->refcnt)
- ecommunity_free (attre->ecommunity);
+ ecommunity_free (&attre->ecommunity);
if (attre->cluster && ! attre->cluster->refcnt)
cluster_free (attre->cluster);
if (attre->transit && ! attre->transit->refcnt)
@@ -708,6 +704,67 @@ bgp_attr_flush (struct attr *attr)
}
}
+/* Implement draft-scudder-idr-optional-transitive behaviour and
+ * avoid resetting sessions for malformed attributes which are
+ * are partial/optional and hence where the error likely was not
+ * introduced by the sending neighbour.
+ */
+static bgp_attr_parse_ret_t
+bgp_attr_malformed (struct peer *peer, u_char type, u_char flag,
+ u_char subcode, u_char *startp, bgp_size_t length)
+{
+ /* Only relax error handling for eBGP peers */
+ if (peer_sort (peer) != BGP_PEER_EBGP)
+ {
+ bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
+ startp, length);
+ return BGP_ATTR_PARSE_ERROR;
+
+ }
+
+ switch (type) {
+ /* where an optional attribute is inconsequential, e.g. it does not affect
+ * route selection, and can be safely ignored then any such attributes
+ * which are malformed should just be ignored and the route processed as
+ * normal.
+ */
+ case BGP_ATTR_AS4_AGGREGATOR:
+ case BGP_ATTR_AGGREGATOR:
+ case BGP_ATTR_ATOMIC_AGGREGATE:
+ return BGP_ATTR_PARSE_PROCEED;
+
+ /* Core attributes, particularly ones which may influence route
+ * selection should always cause session resets
+ */
+ case BGP_ATTR_ORIGIN:
+ case BGP_ATTR_AS_PATH:
+ case BGP_ATTR_NEXT_HOP:
+ case BGP_ATTR_MULTI_EXIT_DISC:
+ case BGP_ATTR_LOCAL_PREF:
+ case BGP_ATTR_COMMUNITIES:
+ case BGP_ATTR_ORIGINATOR_ID:
+ case BGP_ATTR_CLUSTER_LIST:
+ case BGP_ATTR_MP_REACH_NLRI:
+ case BGP_ATTR_MP_UNREACH_NLRI:
+ case BGP_ATTR_EXT_COMMUNITIES:
+ bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
+ startp, length);
+ return BGP_ATTR_PARSE_ERROR;
+ }
+
+ /* Partial optional attributes that are malformed should not cause
+ * the whole session to be reset. Instead treat it as a withdrawal
+ * of the routes, if possible.
+ */
+ if (CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS)
+ && CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)
+ && CHECK_FLAG (flag, BGP_ATTR_FLAG_PARTIAL))
+ return BGP_ATTR_PARSE_WITHDRAW;
+
+ /* default to reset */
+ return BGP_ATTR_PARSE_ERROR;
+}
+
/* Find out what is wrong with the path attribute flag bits and log the error.
"Flag bits" here stand for Optional, Transitive and Partial, but not for
Extended Length. Checking O/T/P bits at once implies, that the attribute
@@ -743,7 +800,7 @@ bgp_attr_flags_diagnose
}
/* Get origin attribute of the update message. */
-static int
+static bgp_attr_parse_ret_t
bgp_attr_origin (struct peer *peer, bgp_size_t length,
struct attr *attr, u_char flag, u_char *startp)
{
@@ -760,8 +817,7 @@ bgp_attr_origin (struct peer *peer, bgp_size_t length,
if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_TRANS)
{
bgp_attr_flags_diagnose (peer, BGP_ATTR_ORIGIN, BGP_ATTR_FLAG_TRANS, flag);
- bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_ORIGIN, flag, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
}
/* If any recognized attribute has Attribute Length that conflicts
@@ -773,10 +829,9 @@ bgp_attr_origin (struct peer *peer, bgp_size_t length,
{
zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
length);
- bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_ORIGIN, flag,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ startp, total);
}
/* Fetch origin attribute. */
@@ -791,12 +846,9 @@ bgp_attr_origin (struct peer *peer, bgp_size_t length,
{
zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
attr->origin);
-
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
- startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_ORIGIN, flag,
+ BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
+ startp, total);
}
/* Set oring attribute flag. */
@@ -804,93 +856,72 @@ bgp_attr_origin (struct peer *peer, bgp_size_t length,
return 0;
}
-/* Parse AS path information. This function is wrapper of aspath_parse.
- *
- * Parses AS_PATH or AS4_PATH.
- *
- * Returns: if valid: address of struct aspath in the hash of known aspaths,
- * with reference count incremented.
- * else: NULL
- *
- * NB: empty AS path (length == 0) is valid. The returned struct aspath will
- * have segments == NULL and str == zero length string (unique).
- */
-static struct aspath *
+
+/* Parse AS path information. This function is wrapper of
+ aspath_parse. */
+static int
bgp_attr_aspath (struct peer *peer, bgp_size_t length,
- struct attr *attr, u_char flag, u_char *startp, int as4_path)
+ struct attr *attr, u_char flag, u_char *startp)
{
- u_char require ;
- struct aspath *asp ;
bgp_size_t total;
total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
- /* Check the attribute flags */
- if (!as4_path && CHECK_FLAG (flag, BGP_ATTR_FLAG_PARTIAL))
+ /* Flags check. */
+ if (CHECK_FLAG (flag, BGP_ATTR_FLAG_PARTIAL))
{
zlog (peer->log, LOG_ERR,
"AS_PATH attribute must not be flagged as \"partial\" (%u)", flag);
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
+ return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
startp, total);
- return NULL;
}
- require = as4_path ? BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
- : BGP_ATTR_FLAG_TRANS ;
-
- if ((flag & (BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS)) != require)
+ if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
{
- const char* path_type ;
-
- path_type = as4_path ? "AS4_PATH" : "AS_PATH" ;
-
- if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS))
- zlog (peer->log, LOG_ERR,
- "%s attribute flag isn't transitive %d", path_type, flag) ;
-
- if ((flag & BGP_ATTR_FLAG_OPTIONAL) != (require & BGP_ATTR_FLAG_OPTIONAL))
- zlog (peer->log, LOG_ERR,
- "%s attribute flag must %sbe optional %d", path_type,
- CHECK_FLAG (require, BGP_ATTR_FLAG_OPTIONAL) ? "" : "not ", flag);
-
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
+ zlog (peer->log, LOG_ERR,
+ "AS_PATH attribute must be flagged as \"transitive\" (%u)", flag);
+ return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
startp, total);
+ }
+
+ if (CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
+ {
+ zlog (peer->log, LOG_ERR,
+ "AS_PATH attribute must not be flagged as \"optional\" (%u)", flag);
+
+ return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
+ BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+ startp, total);
+ }
- return NULL ;
- } ;
-
- /* Parse the AS_PATH/AS4_PATH body.
- *
- * For AS_PATH peer with AS4 => 4Byte ASN otherwise 2Byte ASN
- * AS4_PATH 4Byte ASN
+ /*
+ * peer with AS4 => will get 4Byte ASnums
+ * otherwise, will get 16 Bit
*/
- asp = aspath_parse (peer->ibuf, length,
- as4_path || CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV), as4_path) ;
+ attr->aspath = aspath_parse (peer->ibuf, length,
+ CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
- if (asp != NULL)
+ /* In case of IBGP, length will be zero. */
+ if (! attr->aspath)
{
- attr->flag |= ATTR_FLAG_BIT (as4_path ? BGP_ATTR_AS4_PATH
- : BGP_ATTR_AS_PATH) ;
+ zlog (peer->log, LOG_ERR,
+ "Malformed AS path from %s, length is %d",
+ peer->host, length);
+ return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
+ BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+ NULL, 0);
}
- else
- {
- zlog (peer->log, LOG_ERR, "Malformed AS path length is %d", length);
- /* TODO: should BGP_NOTIFY_UPDATE_MAL_AS_PATH be sent for AS4_PATH ?? */
- bgp_notify_send (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_MAL_AS_PATH);
- } ;
+ /* Set aspath attribute flag. */
+ attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
- return asp ;
+ return BGP_ATTR_PARSE_PROCEED;
}
-static int bgp_attr_aspath_check( struct peer *peer,
- struct attr *attr)
+static bgp_attr_parse_ret_t
+bgp_attr_aspath_check (struct peer *peer, struct attr *attr, u_char flag)
{
/* These checks were part of bgp_attr_aspath, but with
* as4 we should to check aspath things when
@@ -909,10 +940,9 @@ static int bgp_attr_aspath_check( struct peer *peer,
(peer_sort (peer) == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
{
zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
- bgp_notify_send (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_MAL_AS_PATH);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
+ BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+ NULL, 0);
}
/* First AS check for EBGP. */
@@ -923,10 +953,9 @@ static int bgp_attr_aspath_check( struct peer *peer,
{
zlog (peer->log, LOG_ERR,
"%s incorrect first AS (must be %u)", peer->host, peer->as);
- bgp_notify_send (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_MAL_AS_PATH);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
+ BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+ NULL, 0);
}
}
@@ -936,16 +965,57 @@ static int bgp_attr_aspath_check( struct peer *peer,
{
aspath = aspath_dup (attr->aspath);
aspath = aspath_add_seq (aspath, peer->change_local_as);
- aspath_unintern (attr->aspath);
+ aspath_unintern (&attr->aspath);
attr->aspath = aspath_intern (aspath);
}
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
+}
+
+/* Parse AS4 path information. This function is another wrapper of
+ aspath_parse. */
+static int
+bgp_attr_as4_path (struct peer *peer, bgp_size_t length,
+ struct attr *attr, u_char flag, u_char *startp,
+ struct aspath **as4_path)
+{
+ bgp_size_t total;
+
+ total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+
+ /* Flag check. */
+ if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)
+ || !CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
+ {
+ zlog (peer->log, LOG_ERR,
+ "As4-Path attribute flag isn't optional/transitive %d", flag);
+ return bgp_attr_malformed (peer, BGP_ATTR_AS4_PATH, flag,
+ BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+ startp, total);
+ }
+
+ *as4_path = aspath_parse (peer->ibuf, length, 1);
+
+ /* In case of IBGP, length will be zero. */
+ if (!*as4_path)
+ {
+ zlog (peer->log, LOG_ERR,
+ "Malformed AS4 path from %s, length is %d",
+ peer->host, length);
+ return bgp_attr_malformed (peer, BGP_ATTR_AS4_PATH, flag,
+ BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+ NULL, 0);
+ }
+ /* Set aspath attribute flag. */
+ if (as4_path)
+ attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Nexthop attribute. */
-static int
+static bgp_attr_parse_ret_t
bgp_attr_nexthop (struct peer *peer, bgp_size_t length,
struct attr *attr, u_char flag, u_char *startp)
{
@@ -958,8 +1028,7 @@ bgp_attr_nexthop (struct peer *peer, bgp_size_t length,
if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_TRANS)
{
bgp_attr_flags_diagnose (peer, BGP_ATTR_NEXT_HOP, BGP_ATTR_FLAG_TRANS, flag);
- bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_NEXT_HOP, flag, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
}
/* Check nexthop attribute length. */
@@ -968,11 +1037,9 @@ bgp_attr_nexthop (struct peer *peer, bgp_size_t length,
zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
length);
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_NEXT_HOP, flag,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ startp, total);
}
/* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
@@ -987,21 +1054,19 @@ bgp_attr_nexthop (struct peer *peer, bgp_size_t length,
char buf[INET_ADDRSTRLEN];
inet_ntop (AF_INET, &nexthop_h, buf, INET_ADDRSTRLEN);
zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
- startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_NEXT_HOP, flag,
+ BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
+ startp, total);
}
attr->nexthop.s_addr = nexthop_n;
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
/* MED atrribute. */
-static int
+static bgp_attr_parse_ret_t
bgp_attr_med (struct peer *peer, bgp_size_t length,
struct attr *attr, u_char flag, u_char *startp)
{
@@ -1013,8 +1078,9 @@ bgp_attr_med (struct peer *peer, bgp_size_t length,
if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_OPTIONAL)
{
bgp_attr_flags_diagnose (peer, BGP_ATTR_MULTI_EXIT_DISC, BGP_ATTR_FLAG_OPTIONAL, flag);
- bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_MULTI_EXIT_DISC, flag,
+ BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+ startp, total);
}
/* Length check. */
@@ -1022,23 +1088,21 @@ bgp_attr_med (struct peer *peer, bgp_size_t length,
{
zlog (peer->log, LOG_ERR,
"MED attribute length isn't four [%d]", length);
-
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- startp, total);
- return -1;
+
+ return bgp_attr_malformed (peer, BGP_ATTR_MULTI_EXIT_DISC, flag,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ startp, total);
}
attr->med = stream_getl (peer->ibuf);
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Local preference attribute. */
-static int
+static bgp_attr_parse_ret_t
bgp_attr_local_pref (struct peer *peer, bgp_size_t length,
struct attr *attr, u_char flag, u_char *startp)
{
@@ -1049,18 +1113,17 @@ bgp_attr_local_pref (struct peer *peer, bgp_size_t length,
if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_TRANS)
{
bgp_attr_flags_diagnose (peer, BGP_ATTR_LOCAL_PREF, BGP_ATTR_FLAG_TRANS, flag);
- bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_LOCAL_PREF, flag,
+ BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+ startp, total);
}
/* Length check. */
if (length != 4)
{
zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]", length);
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
+ return bgp_attr_malformed (peer, BGP_ATTR_LOCAL_PREF, flag,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
startp, total);
- return -1;
}
/* If it is contained in an UPDATE message that is received from an
@@ -1069,7 +1132,7 @@ bgp_attr_local_pref (struct peer *peer, bgp_size_t length,
if (peer_sort (peer) == BGP_PEER_EBGP)
{
stream_forward_getp (peer->ibuf, length);
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
attr->local_pref = stream_getl (peer->ibuf);
@@ -1077,7 +1140,7 @@ bgp_attr_local_pref (struct peer *peer, bgp_size_t length,
/* Set atomic aggregate flag. */
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Atomic aggregate. */
@@ -1092,25 +1155,24 @@ bgp_attr_atomic (struct peer *peer, bgp_size_t length,
if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_TRANS)
{
bgp_attr_flags_diagnose (peer, BGP_ATTR_ATOMIC_AGGREGATE, BGP_ATTR_FLAG_TRANS, flag);
- bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_ATOMIC_AGGREGATE, flag,
+ BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+ startp, total);
}
/* Length check. */
if (length != 0)
{
zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length);
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_ATOMIC_AGGREGATE, flag,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ startp, total);
}
/* Set atomic aggregate flag. */
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Aggregator attribute */
@@ -1128,34 +1190,28 @@ bgp_attr_aggregator (struct peer *peer, bgp_size_t length,
{
zlog (peer->log, LOG_ERR,
"AGGREGATOR attribute must be flagged as \"optional\" (%u)", flag);
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
+ return bgp_attr_malformed (peer, BGP_ATTR_AGGREGATOR, flag,
BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
startp, total);
- return -1;
}
if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
{
zlog (peer->log, LOG_ERR,
"AGGREGATOR attribute must be flagged as \"transitive\" (%u)", flag);
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
+ return bgp_attr_malformed (peer, BGP_ATTR_AGGREGATOR, flag,
BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
startp, total);
- return -1;
}
/* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
- if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
+ if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
wantedlen = 8;
if (length != wantedlen)
{
zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]", wantedlen, length);
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_AGGREGATOR, flag,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ startp, total);
}
if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
@@ -1167,36 +1223,35 @@ bgp_attr_aggregator (struct peer *peer, bgp_size_t length,
/* Set atomic aggregate flag. */
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
/* New Aggregator attribute */
-static int
+static bgp_attr_parse_ret_t
bgp_attr_as4_aggregator (struct peer *peer, bgp_size_t length,
- struct attr *attr, as_t *as4_aggregator_as,
+ struct attr *attr, u_char flag,
+ as_t *as4_aggregator_as,
struct in_addr *as4_aggregator_addr)
{
if (length != 8)
{
zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]", length);
-
- bgp_notify_send (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_AS4_AGGREGATOR, flag,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ NULL, 0);
}
*as4_aggregator_as = stream_getl (peer->ibuf);
as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
*/
-static int
-bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
+static bgp_attr_parse_ret_t
+bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr, u_char flag,
struct aspath *as4_path, as_t as4_aggregator,
struct in_addr *as4_aggregator_addr)
{
@@ -1204,7 +1259,7 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
struct aspath *newpath;
struct attr_extra *attre = attr->extra;
- if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
+ if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
{
/* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
* if given.
@@ -1222,11 +1277,11 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
peer->host, "AS4 capable peer, yet it sent");
}
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
- if (attr->flag & ( ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))
- && !(attr->flag & ( ATTR_FLAG_BIT( BGP_ATTR_AS_PATH))))
+ if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH))
+ && !(attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))))
{
/* Hu? This is not supposed to happen at all!
* got as4_path and no aspath,
@@ -1238,10 +1293,9 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
zlog (peer->log, LOG_ERR,
"%s BGP not AS4 capable peer sent AS4_PATH but"
" no AS_PATH, cant do anything here", peer->host);
- bgp_notify_send (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_MAL_ATTR);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
+ BGP_NOTIFY_UPDATE_MAL_ATTR,
+ NULL, 0);
}
/* We have a asn16 peer. First, look for AS4_AGGREGATOR
@@ -1249,7 +1303,7 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
*/
if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
{
- if ( attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
+ if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
{
assert (attre);
@@ -1265,7 +1319,7 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
* Aggregating node and the AS_PATH is to be
* constructed "as in all other cases"
*/
- if ( attre->aggregator_as != BGP_AS_TRANS )
+ if (attre->aggregator_as != BGP_AS_TRANS)
{
/* ignore */
if ( BGP_DEBUG(as4, AS4))
@@ -1300,24 +1354,27 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
}
/* need to reconcile NEW_AS_PATH and AS_PATH */
- if ( !ignore_as4_path && (attr->flag & ( ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))) )
+ if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
{
newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
- aspath_unintern (attr->aspath);
+ aspath_unintern (&attr->aspath);
attr->aspath = aspath_intern (newpath);
}
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Community attribute. */
-static int
+static bgp_attr_parse_ret_t
bgp_attr_community (struct peer *peer, bgp_size_t length,
- struct attr *attr, u_char flag)
+ struct attr *attr, u_char flag, u_char *startp)
{
+ bgp_size_t total
+ = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+
if (length == 0)
{
attr->community = NULL;
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
attr->community =
@@ -1327,15 +1384,17 @@ bgp_attr_community (struct peer *peer, bgp_size_t length,
stream_forward_getp (peer->ibuf, length);
if (!attr->community)
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_COMMUNITIES, flag,
+ BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+ startp, total);
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Originator ID attribute. */
-static int
+static bgp_attr_parse_ret_t
bgp_attr_originator_id (struct peer *peer, bgp_size_t length,
struct attr *attr, u_char flag, u_char *startp)
{
@@ -1346,19 +1405,18 @@ bgp_attr_originator_id (struct peer *peer, bgp_size_t length,
if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_OPTIONAL)
{
bgp_attr_flags_diagnose (peer, BGP_ATTR_ORIGINATOR_ID, BGP_ATTR_FLAG_OPTIONAL, flag);
- bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_ORIGINATOR_ID, flag,
+ BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+ startp, total);
}
/* Length check. */
if (length != 4)
{
zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_ORIGINATOR_ID, flag,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ startp, total);
}
(bgp_attr_extra_get (attr))->originator_id.s_addr
@@ -1366,11 +1424,11 @@ bgp_attr_originator_id (struct peer *peer, bgp_size_t length,
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Cluster list attribute. */
-static int
+static bgp_attr_parse_ret_t
bgp_attr_cluster_list (struct peer *peer, bgp_size_t length,
struct attr *attr, u_char flag, u_char *startp)
{
@@ -1381,29 +1439,29 @@ bgp_attr_cluster_list (struct peer *peer, bgp_size_t length,
if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_OPTIONAL)
{
bgp_attr_flags_diagnose (peer, BGP_ATTR_CLUSTER_LIST, BGP_ATTR_FLAG_OPTIONAL, flag);
- bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_CLUSTER_LIST, flag,
+ BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+ startp, total);
}
/* Check length. */
if (length % 4)
{
zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_CLUSTER_LIST, flag,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ startp, total);
}
(bgp_attr_extra_get (attr))->cluster
= cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
-
- stream_forward_getp (peer->ibuf, length);;
+
+ /* XXX: Fix cluster_parse to use stream API and then remove this */
+ stream_forward_getp (peer->ibuf, length);
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Multiprotocol reachability information parse. */
@@ -1425,8 +1483,9 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_OPTIONAL)
{
bgp_attr_flags_diagnose (peer, BGP_ATTR_MP_REACH_NLRI, BGP_ATTR_FLAG_OPTIONAL, flag);
- bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_MP_REACH_NLRI, flag,
+ BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+ startp, total);
}
/* Set end of packet. */
s = BGP_INPUT(peer);
@@ -1439,7 +1498,7 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
{
zlog_info ("%s: %s sent invalid length, %lu",
__func__, peer->host, (unsigned long)length);
- return -1;
+ return BGP_ATTR_PARSE_ERROR;
}
/* Load AFI, SAFI. */
@@ -1453,7 +1512,7 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
{
zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
__func__, peer->host, attre->mp_nexthop_len);
- return -1;
+ return BGP_ATTR_PARSE_ERROR;
}
/* Nexthop length check. */
@@ -1466,14 +1525,9 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
break;
case 12:
- {
- u_int32_t rd_high;
- u_int32_t rd_low;
-
- rd_high = stream_getl (s);
- rd_low = stream_getl (s);
- stream_get (&attre->mp_nexthop_global_in, s, 4);
- }
+ stream_getl (s); /* RD high */
+ stream_getl (s); /* RD low */
+ stream_get (&attre->mp_nexthop_global_in, s, 4);
break;
#ifdef HAVE_IPV6
case 16:
@@ -1501,14 +1555,14 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
default:
zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
__func__, peer->host, attre->mp_nexthop_len);
- return -1;
+ return BGP_ATTR_PARSE_ERROR;
}
if (!LEN_LEFT)
{
zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
__func__, peer->host);
- return -1;
+ return BGP_ATTR_PARSE_ERROR;
}
{
@@ -1524,7 +1578,7 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
{
zlog_info ("%s: (%s) Failed to read NLRI",
__func__, peer->host);
- return -1;
+ return BGP_ATTR_PARSE_ERROR;
}
if (safi != SAFI_MPLS_LABELED_VPN)
@@ -1534,7 +1588,7 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
{
zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
__func__, peer->host);
- return -1;
+ return BGP_ATTR_PARSE_ERROR;
}
}
@@ -1545,7 +1599,7 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
stream_forward_getp (s, nlri_len);
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
#undef LEN_LEFT
}
@@ -1567,15 +1621,16 @@ bgp_mp_unreach_parse (struct peer *peer, const bgp_size_t length,
if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_OPTIONAL)
{
bgp_attr_flags_diagnose (peer, BGP_ATTR_MP_UNREACH_NLRI, BGP_ATTR_FLAG_OPTIONAL, flag);
- bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_MP_UNREACH_NLRI, flag,
+ BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+ startp, total);
}
s = peer->ibuf;
#define BGP_MP_UNREACH_MIN_SIZE 3
if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
- return -1;
+ return BGP_ATTR_PARSE_ERROR;
afi = stream_getw (s);
safi = stream_getc (s);
@@ -1586,7 +1641,7 @@ bgp_mp_unreach_parse (struct peer *peer, const bgp_size_t length,
{
ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len);
if (ret < 0)
- return -1;
+ return BGP_ATTR_PARSE_ERROR;
}
mp_withdraw->afi = afi;
@@ -1596,20 +1651,23 @@ bgp_mp_unreach_parse (struct peer *peer, const bgp_size_t length,
stream_forward_getp (s, withdraw_len);
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Extended Community attribute. */
-static int
+static bgp_attr_parse_ret_t
bgp_attr_ext_communities (struct peer *peer, bgp_size_t length,
- struct attr *attr, u_char flag)
+ struct attr *attr, u_char flag, u_char *startp)
{
+ bgp_size_t total
+ = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+
if (length == 0)
{
if (attr->extra)
attr->extra->ecommunity = NULL;
/* Empty extcomm doesn't seem to be invalid per se */
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
(bgp_attr_extra_get (attr))->ecommunity =
@@ -1618,15 +1676,17 @@ bgp_attr_ext_communities (struct peer *peer, bgp_size_t length,
stream_forward_getp (peer->ibuf, length);
if (!attr->extra->ecommunity)
- return -1;
+ return bgp_attr_malformed (peer, BGP_ATTR_EXT_COMMUNITIES,
+ flag, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+ startp, total);
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
/* BGP unknown attribute treatment. */
-static int
+static bgp_attr_parse_ret_t
bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag,
u_char type, bgp_size_t length, u_char *startp)
{
@@ -1652,20 +1712,17 @@ bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag,
then the Error Subcode is set to Unrecognized Well-known
Attribute. The Data field contains the unrecognized attribute
(type, length and value). */
- if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
+ if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
{
- /* Adjust startp to do not include flag value. */
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_UNREC_ATTR,
- startp, total);
- return -1;
+ return bgp_attr_malformed (peer, type, flag,
+ BGP_NOTIFY_UPDATE_UNREC_ATTR,
+ startp, total);
}
/* Unrecognized non-transitive optional attributes must be quietly
ignored and not passed along to other BGP peers. */
if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
/* If a path with recognized transitive optional attribute is
accepted and passed along to other BGP peers and the Partial bit
@@ -1688,17 +1745,17 @@ bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag,
memcpy (transit->val + transit->length, startp, total);
transit->length += total;
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Read attribute of update packet. This function is called from
bgp_update() in bgpd.c. */
-int
+bgp_attr_parse_ret_t
bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
{
int ret;
- u_char flag;
+ u_char flag = 0;
u_char type = 0;
bgp_size_t length;
u_char *startp, *endp;
@@ -1715,7 +1772,7 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
/* End pointer of BGP attribute. */
endp = BGP_INPUT_PNT (peer) + size;
-
+
/* Get attributes to the end of attribute length. */
while (BGP_INPUT_PNT (peer) < endp)
{
@@ -1731,7 +1788,7 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
bgp_notify_send (peer,
BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- return -1;
+ return BGP_ATTR_PARSE_ERROR;
}
/* Fetch attribute flag and type. */
@@ -1754,7 +1811,7 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
bgp_notify_send (peer,
BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- return -1;
+ return BGP_ATTR_PARSE_ERROR;
}
/* Check extended attribue length bit. */
@@ -1776,7 +1833,7 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
bgp_notify_send (peer,
BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MAL_ATTR);
- return -1;
+ return BGP_ATTR_PARSE_ERROR;
}
/* Set type to bitmap to check duplicate attribute. `type' is
@@ -1794,7 +1851,7 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
bgp_notify_send (peer,
BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- return -1;
+ return BGP_ATTR_PARSE_ERROR;
}
/* OK check attribute and store it's value. */
@@ -1804,12 +1861,10 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
ret = bgp_attr_origin (peer, length, attr, flag, startp);
break;
case BGP_ATTR_AS_PATH:
- attr->aspath = bgp_attr_aspath (peer, length, attr, flag, startp, 0);
- ret = attr->aspath ? 0 : -1 ;
+ ret = bgp_attr_aspath (peer, length, attr, flag, startp);
break;
case BGP_ATTR_AS4_PATH:
- as4_path = bgp_attr_aspath (peer, length, attr, flag, startp, 1);
- ret = as4_path ? 0 : -1 ;
+ ret = bgp_attr_as4_path (peer, length, attr, flag, startp, &as4_path);
break;
case BGP_ATTR_NEXT_HOP:
ret = bgp_attr_nexthop (peer, length, attr, flag, startp);
@@ -1827,10 +1882,12 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
ret = bgp_attr_aggregator (peer, length, attr, flag, startp);
break;
case BGP_ATTR_AS4_AGGREGATOR:
- ret = bgp_attr_as4_aggregator (peer, length, attr, &as4_aggregator, &as4_aggregator_addr);
+ ret = bgp_attr_as4_aggregator (peer, length, attr, flag,
+ &as4_aggregator,
+ &as4_aggregator_addr);
break;
case BGP_ATTR_COMMUNITIES:
- ret = bgp_attr_community (peer, length, attr, flag);
+ ret = bgp_attr_community (peer, length, attr, flag, startp);
break;
case BGP_ATTR_ORIGINATOR_ID:
ret = bgp_attr_originator_id (peer, length, attr, flag, startp);
@@ -1845,26 +1902,39 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
ret = bgp_mp_unreach_parse (peer, length, flag, startp, mp_withdraw);
break;
case BGP_ATTR_EXT_COMMUNITIES:
- ret = bgp_attr_ext_communities (peer, length, attr, flag);
+ ret = bgp_attr_ext_communities (peer, length, attr, flag, startp);
break;
default:
ret = bgp_attr_unknown (peer, attr, flag, type, length, startp);
break;
}
-
- /* If error occured immediately return to the caller. */
- if (ret < 0)
+
+ /* If hard error occured immediately return to the caller. */
+ if (ret == BGP_ATTR_PARSE_ERROR)
{
zlog (peer->log, LOG_WARNING,
"%s: Attribute %s, parse error",
peer->host,
LOOKUP (attr_str, type));
- bgp_notify_send (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_MAL_ATTR);
- return ret;
+ bgp_notify_send (peer,
+ BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_MAL_ATTR);
+ if (as4_path)
+ aspath_unintern (&as4_path);
+ return ret;
}
-
+ if (ret == BGP_ATTR_PARSE_WITHDRAW)
+ {
+
+ zlog (peer->log, LOG_WARNING,
+ "%s: Attribute %s, parse error - treating as withdrawal",
+ peer->host,
+ LOOKUP (attr_str, type));
+ if (as4_path)
+ aspath_unintern (&as4_path);
+ return ret;
+ }
+
/* Check the fetched length. */
if (BGP_INPUT_PNT (peer) != attr_endp)
{
@@ -1874,7 +1944,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
bgp_notify_send (peer,
BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- return -1;
+ if (as4_path)
+ aspath_unintern (&as4_path);
+ return BGP_ATTR_PARSE_ERROR;
}
}
@@ -1887,7 +1959,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
bgp_notify_send (peer,
BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- return -1;
+ if (as4_path)
+ aspath_unintern (&as4_path);
+ return BGP_ATTR_PARSE_ERROR;
}
/*
@@ -1901,19 +1975,22 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
* all attributes first, including these 32bit ones, and now,
* afterwards, we look what and if something is to be done for as4.
*/
- if (bgp_attr_munge_as4_attrs (peer, attr, as4_path,
+ if (bgp_attr_munge_as4_attrs (peer, attr, flag, as4_path,
as4_aggregator, &as4_aggregator_addr))
- return -1;
+ {
+ if (as4_path)
+ aspath_unintern (&as4_path);
+ return BGP_ATTR_PARSE_ERROR;
+ }
/* At this stage, we have done all fiddling with as4, and the
* resulting info is in attr->aggregator resp. attr->aspath
* so we can chuck as4_aggregator and as4_path alltogether in
* order to save memory
*/
- if ( as4_path )
+ if (as4_path)
{
- aspath_unintern( as4_path ); /* unintern - it is in the hash */
- as4_path = NULL;
+ aspath_unintern (&as4_path); /* unintern - it is in the hash */
/* The flag that we got this is still there, but that does not
* do any trouble
*/
@@ -1928,10 +2005,10 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
* Finally do the checks on the aspath we did not do yet
* because we waited for a potentially synthesized aspath.
*/
- if ( attr->flag & ( ATTR_FLAG_BIT( BGP_ATTR_AS_PATH)))
+ if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
{
- ret = bgp_attr_aspath_check( peer, attr );
- if ( ret < 0 )
+ ret = bgp_attr_aspath_check (peer, attr, flag);
+ if (ret != BGP_ATTR_PARSE_PROCEED)
return ret;
}
@@ -1939,7 +2016,7 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
if (attr->extra && attr->extra->transit)
attr->extra->transit = transit_intern (attr->extra->transit);
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Well-known attribute check. */
@@ -1970,9 +2047,9 @@ bgp_attr_check (struct peer *peer, struct attr *attr)
BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MISS_ATTR,
&type, 1);
- return -1;
+ return BGP_ATTR_PARSE_ERROR;
}
- return 0;
+ return BGP_ATTR_PARSE_PROCEED;
}
int stream_put_prefix (struct stream *, struct prefix *);
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 4cb70678..e6300740 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -132,17 +132,25 @@ struct transit
#define ATTR_FLAG_BIT(X) (1 << ((X) - 1))
+typedef enum {
+ BGP_ATTR_PARSE_PROCEED = 0,
+ BGP_ATTR_PARSE_ERROR = -1,
+ BGP_ATTR_PARSE_WITHDRAW = -2,
+} bgp_attr_parse_ret_t;
+
/* Prototypes. */
extern void bgp_attr_init (void);
extern void bgp_attr_finish (void);
-extern int bgp_attr_parse (struct peer *, struct attr *, bgp_size_t,
- struct bgp_nlri *, struct bgp_nlri *);
+extern bgp_attr_parse_ret_t bgp_attr_parse (struct peer *, struct attr *,
+ bgp_size_t, struct bgp_nlri *,
+ struct bgp_nlri *);
extern int bgp_attr_check (struct peer *, struct attr *);
extern struct attr_extra *bgp_attr_extra_get (struct attr *);
extern void bgp_attr_extra_free (struct attr *);
extern void bgp_attr_dup (struct attr *, struct attr *);
extern struct attr *bgp_attr_intern (struct attr *attr);
-extern void bgp_attr_unintern (struct attr *);
+extern void bgp_attr_unintern_sub (struct attr *);
+extern void bgp_attr_unintern (struct attr **);
extern void bgp_attr_flush (struct attr *);
extern struct attr *bgp_attr_default_set (struct attr *attr, u_char);
extern struct attr *bgp_attr_default_intern (u_char);
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index d6601674..6c9976e3 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -70,7 +70,7 @@ community_entry_free (struct community_entry *entry)
if (entry->config)
XFREE (MTYPE_ECOMMUNITY_STR, entry->config);
if (entry->u.ecom)
- ecommunity_free (entry->u.ecom);
+ ecommunity_free (&entry->u.ecom);
break;
case COMMUNITY_LIST_EXPANDED:
case EXTCOMMUNITY_LIST_EXPANDED:
@@ -806,7 +806,7 @@ extcommunity_list_unset (struct community_list_handler *ch,
entry = community_list_entry_lookup (list, str, direct);
if (ecom)
- ecommunity_free (ecom);
+ ecommunity_free (&ecom);
if (regex)
bgp_regex_free (regex);
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index ae1d7a15..2ba45f6e 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -321,21 +321,22 @@ community_intern (struct community *com)
/* Free community attribute. */
void
-community_unintern (struct community *com)
+community_unintern (struct community **com)
{
struct community *ret;
- if (com->refcnt)
- com->refcnt--;
+ if ((*com)->refcnt)
+ (*com)->refcnt--;
/* Pull off from hash. */
- if (com->refcnt == 0)
+ if ((*com)->refcnt == 0)
{
/* Community value com must exist in hash. */
- ret = (struct community *) hash_release (comhash, com);
+ ret = (struct community *) hash_release (comhash, *com);
assert (ret != NULL);
- community_free (com);
+ community_free (*com);
+ *com = NULL;
}
}
diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h
index bc1e56ef..9e483770 100644
--- a/bgpd/bgp_community.h
+++ b/bgpd/bgp_community.h
@@ -57,7 +57,7 @@ extern void community_free (struct community *);
extern struct community *community_uniq_sort (struct community *);
extern struct community *community_parse (u_int32_t *, u_short);
extern struct community *community_intern (struct community *);
-extern void community_unintern (struct community *);
+extern void community_unintern (struct community **);
extern char *community_str (struct community *);
extern unsigned int community_hash_make (struct community *);
extern struct community *community_str2com (const char *);
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index e7eb0a07..440c15a4 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -42,13 +42,14 @@ ecommunity_new (void)
/* Allocate ecommunities. */
void
-ecommunity_free (struct ecommunity *ecom)
+ecommunity_free (struct ecommunity **ecom)
{
- if (ecom->val)
- XFREE (MTYPE_ECOMMUNITY_VAL, ecom->val);
- if (ecom->str)
- XFREE (MTYPE_ECOMMUNITY_STR, ecom->str);
- XFREE (MTYPE_ECOMMUNITY, ecom);
+ if ((*ecom)->val)
+ XFREE (MTYPE_ECOMMUNITY_VAL, (*ecom)->val);
+ if ((*ecom)->str)
+ XFREE (MTYPE_ECOMMUNITY_STR, (*ecom)->str);
+ XFREE (MTYPE_ECOMMUNITY, *ecom);
+ ecom = NULL;
}
/* Add a new Extended Communities value to Extended Communities
@@ -197,7 +198,7 @@ ecommunity_intern (struct ecommunity *ecom)
find = (struct ecommunity *) hash_get (ecomhash, ecom, hash_alloc_intern);
if (find != ecom)
- ecommunity_free (ecom);
+ ecommunity_free (&ecom);
find->refcnt++;
@@ -209,18 +210,18 @@ ecommunity_intern (struct ecommunity *ecom)
/* Unintern Extended Communities Attribute. */
void
-ecommunity_unintern (struct ecommunity *ecom)
+ecommunity_unintern (struct ecommunity **ecom)
{
struct ecommunity *ret;
- if (ecom->refcnt)
- ecom->refcnt--;
-
+ if ((*ecom)->refcnt)
+ (*ecom)->refcnt--;
+
/* Pull off from hash. */
- if (ecom->refcnt == 0)
+ if ((*ecom)->refcnt == 0)
{
/* Extended community must be in the hash. */
- ret = (struct ecommunity *) hash_release (ecomhash, ecom);
+ ret = (struct ecommunity *) hash_release (ecomhash, *ecom);
assert (ret != NULL);
ecommunity_free (ecom);
@@ -516,7 +517,7 @@ ecommunity_str2com (const char *str, int type, int keyword_included)
if (! keyword_included || keyword)
{
if (ecom)
- ecommunity_free (ecom);
+ ecommunity_free (&ecom);
return NULL;
}
keyword = 1;
@@ -536,7 +537,7 @@ ecommunity_str2com (const char *str, int type, int keyword_included)
if (! keyword)
{
if (ecom)
- ecommunity_free (ecom);
+ ecommunity_free (&ecom);
return NULL;
}
keyword = 0;
@@ -549,7 +550,7 @@ ecommunity_str2com (const char *str, int type, int keyword_included)
case ecommunity_token_unknown:
default:
if (ecom)
- ecommunity_free (ecom);
+ ecommunity_free (&ecom);
return NULL;
}
}
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index 942fdc73..2f59dc40 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -67,13 +67,13 @@ struct ecommunity_val
extern void ecommunity_init (void);
extern void ecommunity_finish (void);
-extern void ecommunity_free (struct ecommunity *);
+extern void ecommunity_free (struct ecommunity **);
extern struct ecommunity *ecommunity_parse (u_int8_t *, u_short);
extern struct ecommunity *ecommunity_dup (struct ecommunity *);
extern struct ecommunity *ecommunity_merge (struct ecommunity *, struct ecommunity *);
extern struct ecommunity *ecommunity_intern (struct ecommunity *);
extern int ecommunity_cmp (const void *, const void *);
-extern void ecommunity_unintern (struct ecommunity *);
+extern void ecommunity_unintern (struct ecommunity **);
extern unsigned int ecommunity_hash_make (void *);
extern struct ecommunity *ecommunity_str2com (const char *, int, int);
extern char *ecommunity_ecom2str (struct ecommunity *, int);
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index f835fe77..8dede587 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -247,7 +247,15 @@ bgp_exit (int status)
if (retain_mode)
if_add_hook (IF_DELETE_HOOK, NULL);
for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
- if_delete (ifp);
+ {
+ struct listnode *c_node, *c_nnode;
+ struct connected *c;
+
+ for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c))
+ bgp_connected_delete (c);
+
+ if_delete (ifp);
+ }
list_free (iflist);
/* reverse bgp_attr_init */
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index b5c4c602..a7dca531 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -30,6 +30,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "command.h"
#include "privs.h"
#include "linklist.h"
+#include "network.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_fsm.h"
@@ -150,6 +151,7 @@ bgp_accept (struct thread *thread)
zlog_err ("[Error] BGP socket accept failed (%s)", safe_strerror (errno));
return -1;
}
+ set_nonblocking (bgp_sock);
if (BGP_DEBUG (events, EVENTS))
zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf));
@@ -172,8 +174,11 @@ bgp_accept (struct thread *thread)
}
/* In case of peer is EBGP, we should set TTL for this connection. */
- if (peer_sort (peer1) == BGP_PEER_EBGP)
+ if (peer_sort (peer1) == BGP_PEER_EBGP) {
sockopt_ttl (peer1->su.sa.sa_family, bgp_sock, peer1->ttl);
+ if (peer1->gtsm_hops)
+ sockopt_minttl (peer1->su.sa.sa_family, bgp_sock, MAXTTL + 1 - peer1->gtsm_hops);
+ }
/* Make dummy peer until read Open packet. */
if (BGP_DEBUG (events, EVENTS))
@@ -302,8 +307,11 @@ bgp_connect (struct peer *peer)
return -1;
/* If we can get socket for the peer, adjest TTL and make connection. */
- if (peer_sort (peer) == BGP_PEER_EBGP)
+ if (peer_sort (peer) == BGP_PEER_EBGP) {
sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
+ if (peer->gtsm_hops)
+ sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - peer->gtsm_hops);
+ }
sockopt_reuseaddr (peer->fd);
sockopt_reuseport (peer->fd);
@@ -455,7 +463,10 @@ bgp_socket (unsigned short port, const char *address)
zlog_err ("socket: %s", safe_strerror (errno));
continue;
}
-
+
+ /* if we intend to implement ttl-security, this socket needs ttl=255 */
+ sockopt_ttl (ainfo->ai_family, sock, MAXTTL);
+
ret = bgp_listener (sock, ainfo->ai_addr, ainfo->ai_addrlen);
if (ret == 0)
++count;
@@ -488,6 +499,9 @@ bgp_socket (unsigned short port, const char *address)
return sock;
}
+ /* if we intend to implement ttl-security, this socket needs ttl=255 */
+ sockopt_ttl (AF_INET, sock, MAXTTL);
+
memset (&sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = htons (port);
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index f8d1adec..e9c78b3f 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -264,6 +264,8 @@ bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
if (bnc->metric != oldbnc->metric)
bnc->metricchanged = 1;
+
+ bgp_unlock_node (oldrn);
}
}
}
@@ -340,6 +342,8 @@ bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
if (bnc->metric != oldbnc->metric)
bnc->metricchanged = 1;
+
+ bgp_unlock_node (oldrn);
}
}
}
@@ -541,7 +545,7 @@ bgp_connected_add (struct connected *ifc)
}
else
{
- bc = XCALLOC (0, sizeof (struct bgp_connected_ref));
+ bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
bc->refcnt = 1;
rn->info = bc;
}
@@ -566,7 +570,7 @@ bgp_connected_add (struct connected *ifc)
}
else
{
- bc = XCALLOC (0, sizeof (struct bgp_connected_ref));
+ bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
bc->refcnt = 1;
rn->info = bc;
}
@@ -606,7 +610,7 @@ bgp_connected_delete (struct connected *ifc)
bc->refcnt--;
if (bc->refcnt == 0)
{
- XFREE (0, bc);
+ XFREE (MTYPE_BGP_CONN, bc);
rn->info = NULL;
}
bgp_unlock_node (rn);
@@ -632,7 +636,7 @@ bgp_connected_delete (struct connected *ifc)
bc->refcnt--;
if (bc->refcnt == 0)
{
- XFREE (0, bc);
+ XFREE (MTYPE_BGP_CONN, bc);
rn->info = NULL;
}
bgp_unlock_node (rn);
@@ -1101,11 +1105,15 @@ bgp_multiaccess_check_v4 (struct in_addr nexthop, char *peer)
rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p1);
if (! rn1)
return 0;
+ bgp_unlock_node (rn1);
rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p2);
if (! rn2)
return 0;
+ bgp_unlock_node (rn2);
+ /* This is safe, even with above unlocks, since we are just
+ comparing pointers to the objects, not the objects themselves. */
if (rn1 == rn2)
return 1;
@@ -1330,6 +1338,9 @@ bgp_scan_init (void)
void
bgp_scan_finish (void)
{
+ /* Only the current one needs to be reset. */
+ bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]);
+
bgp_table_unlock (cache1_table[AFI_IP]);
cache1_table[AFI_IP] = NULL;
@@ -1340,6 +1351,9 @@ bgp_scan_finish (void)
bgp_connected_table[AFI_IP] = NULL;
#ifdef HAVE_IPV6
+ /* Only the current one needs to be reset. */
+ bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]);
+
bgp_table_unlock (cache1_table[AFI_IP6]);
cache1_table[AFI_IP6] = NULL;
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index fc653e21..f5a74d1b 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -206,7 +206,7 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
/* Synchnorize attribute. */
if (adj->attr)
- bgp_attr_unintern (adj->attr);
+ bgp_attr_unintern (&adj->attr);
else
peer->scount[afi][safi]++;
@@ -598,7 +598,6 @@ bgp_write (struct thread *thread)
struct stream *s;
int num;
unsigned int count = 0;
- int write_errno;
/* Yes first of all get peer pointer. */
peer = THREAD_ARG (thread);
@@ -611,46 +610,37 @@ bgp_write (struct thread *thread)
return 0;
}
- /* Nonblocking write until TCP output buffer is full. */
- while (1)
+ s = bgp_write_packet (peer);
+ if (!s)
+ return 0; /* nothing to send */
+
+ sockopt_cork (peer->fd, 1);
+
+ /* Nonblocking write until TCP output buffer is full. */
+ do
{
int writenum;
- int val;
-
- s = bgp_write_packet (peer);
- if (! s)
- return 0;
-
- /* XXX: FIXME, the socket should be NONBLOCK from the start
- * status shouldnt need to be toggled on each write
- */
- val = fcntl (peer->fd, F_GETFL, 0);
- fcntl (peer->fd, F_SETFL, val|O_NONBLOCK);
/* Number of bytes to be sent. */
writenum = stream_get_endp (s) - stream_get_getp (s);
/* Call write() system call. */
num = write (peer->fd, STREAM_PNT (s), writenum);
- write_errno = errno;
- fcntl (peer->fd, F_SETFL, val);
- if (num <= 0)
+ if (num < 0)
{
- /* Partial write. */
- if (write_errno == EWOULDBLOCK || write_errno == EAGAIN)
- break;
+ /* write failed either retry needed or error */
+ if (ERRNO_IO_RETRY(errno))
+ break;
- BGP_EVENT_ADD (peer, TCP_fatal_error);
+ BGP_EVENT_ADD (peer, TCP_fatal_error);
return 0;
}
+
if (num != writenum)
{
+ /* Partial write */
stream_forward_getp (s, num);
-
- if (write_errno == EAGAIN)
- break;
-
- continue;
+ break;
}
/* Retrieve BGP packet type. */
@@ -691,13 +681,14 @@ bgp_write (struct thread *thread)
/* OK we send packet so delete it. */
bgp_packet_delete (peer);
-
- if (++count >= BGP_WRITE_PACKET_MAX)
- break;
}
+ while (++count < BGP_WRITE_PACKET_MAX &&
+ (s = bgp_write_packet (peer)) != NULL);
if (bgp_write_proceed (peer))
BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+ else
+ sockopt_cork (peer->fd, 0);
return 0;
}
@@ -706,7 +697,7 @@ bgp_write (struct thread *thread)
static int
bgp_write_notify (struct peer *peer)
{
- int ret;
+ int ret, val;
u_char type;
struct stream *s;
@@ -716,7 +707,10 @@ bgp_write_notify (struct peer *peer)
return 0;
assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
- /* I'm not sure fd is writable. */
+ /* Put socket in blocking mode. */
+ val = fcntl (peer->fd, F_GETFL, 0);
+ fcntl (peer->fd, F_SETFL, val & ~O_NONBLOCK);
+
ret = writen (peer->fd, STREAM_DATA (s), stream_get_endp (s));
if (ret <= 0)
{
@@ -1602,26 +1596,47 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
BGP_NOTIFY_UPDATE_MAL_ATTR);
return -1;
}
+
+ /* Certain attribute parsing errors should not be considered bad enough
+ * to reset the session for, most particularly any partial/optional
+ * attributes that have 'tunneled' over speakers that don't understand
+ * them. Instead we withdraw only the prefix concerned.
+ *
+ * Complicates the flow a little though..
+ */
+ bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
+ /* This define morphs the update case into a withdraw when lower levels
+ * have signalled an error condition where this is best.
+ */
+#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
/* Parse attribute when it exists. */
if (attribute_len)
{
- ret = bgp_attr_parse (peer, &attr, attribute_len,
+ attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
&mp_update, &mp_withdraw);
- if (ret < 0)
+ if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
return -1;
}
-
+
/* Logging the attribute. */
- if (BGP_DEBUG (update, UPDATE_IN))
+ if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
+ || BGP_DEBUG (update, UPDATE_IN))
{
ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
+ int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
+ ? LOG_ERR : LOG_DEBUG;
+
+ if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
+ zlog (peer->log, LOG_ERR,
+ "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
+ peer->host);
if (ret)
- zlog (peer->log, LOG_DEBUG, "%s rcvd UPDATE w/ attr: %s",
+ zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
peer->host, attrstr);
}
-
+
/* Network Layer Reachability Information. */
update_len = end - stream_pnt (s);
@@ -1630,7 +1645,12 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
/* Check NLRI packet format and prefix length. */
ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
if (ret < 0)
- return -1;
+ {
+ bgp_attr_unintern_sub (&attr);
+ if (attr.extra)
+ bgp_attr_extra_free (&attr);
+ return -1;
+ }
/* Set NLRI portion to structure. */
update.afi = AFI_IP;
@@ -1653,15 +1673,20 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
update. */
ret = bgp_attr_check (peer, &attr);
if (ret < 0)
- return -1;
+ {
+ bgp_attr_unintern_sub (&attr);
+ if (attr.extra)
+ bgp_attr_extra_free (&attr);
+ return -1;
+ }
- bgp_nlri_parse (peer, &attr, &update);
+ bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
}
if (mp_update.length
&& mp_update.afi == AFI_IP
&& mp_update.safi == SAFI_UNICAST)
- bgp_nlri_parse (peer, &attr, &mp_update);
+ bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
if (mp_withdraw.length
&& mp_withdraw.afi == AFI_IP
@@ -1688,7 +1713,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
if (mp_update.length
&& mp_update.afi == AFI_IP
&& mp_update.safi == SAFI_MULTICAST)
- bgp_nlri_parse (peer, &attr, &mp_update);
+ bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
if (mp_withdraw.length
&& mp_withdraw.afi == AFI_IP
@@ -1718,7 +1743,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
if (mp_update.length
&& mp_update.afi == AFI_IP6
&& mp_update.safi == SAFI_UNICAST)
- bgp_nlri_parse (peer, &attr, &mp_update);
+ bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
if (mp_withdraw.length
&& mp_withdraw.afi == AFI_IP6
@@ -1747,7 +1772,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
if (mp_update.length
&& mp_update.afi == AFI_IP6
&& mp_update.safi == SAFI_MULTICAST)
- bgp_nlri_parse (peer, &attr, &mp_update);
+ bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
if (mp_withdraw.length
&& mp_withdraw.afi == AFI_IP6
@@ -1775,7 +1800,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
if (mp_update.length
&& mp_update.afi == AFI_IP
&& mp_update.safi == SAFI_MPLS_LABELED_VPN)
- bgp_nlri_parse_vpnv4 (peer, &attr, &mp_update);
+ bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
if (mp_withdraw.length
&& mp_withdraw.afi == AFI_IP
@@ -1797,21 +1822,10 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
/* Everything is done. We unintern temporary structures which
interned in bgp_attr_parse(). */
- if (attr.aspath)
- aspath_unintern (attr.aspath);
- if (attr.community)
- community_unintern (attr.community);
+ bgp_attr_unintern_sub (&attr);
if (attr.extra)
- {
- if (attr.extra->ecommunity)
- ecommunity_unintern (attr.extra->ecommunity);
- if (attr.extra->cluster)
- cluster_unintern (attr.extra->cluster);
- if (attr.extra->transit)
- transit_unintern (attr.extra->transit);
- bgp_attr_extra_free (&attr);
- }
-
+ bgp_attr_extra_free (&attr);
+
/* If peering is stopped due to some reason, do not generate BGP
event. */
if (peer->status != Established)
@@ -2028,7 +2042,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
* as possible without going beyond the bounds of the entry,
* to maximise debug information.
*/
- int ok ;
+ int ok;
memset (&orfp, 0, sizeof (struct orf_prefix));
common = *p_pnt++;
/* after ++: p_pnt <= p_end */
@@ -2042,9 +2056,9 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
ok = ((p_end - p_pnt) >= sizeof(u_int32_t)) ;
if (ok)
{
- memcpy (&seq, p_pnt, sizeof (u_int32_t));
- p_pnt += sizeof (u_int32_t);
- orfp.seq = ntohl (seq);
+ memcpy (&seq, p_pnt, sizeof (u_int32_t));
+ p_pnt += sizeof (u_int32_t);
+ orfp.seq = ntohl (seq);
}
else
p_pnt = p_end ;
@@ -2082,16 +2096,17 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, BUFSIZ),
orfp.p.prefixlen, orfp.ge, orfp.le,
ok ? "" : " MALFORMED");
-
+
if (ok)
- ret = prefix_bgp_orf_set (name, afi, &orfp,
- (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
- (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
+ ret = prefix_bgp_orf_set (name, afi, &orfp,
+ (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
+ (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
if (!ok || (ret != CMD_SUCCESS))
{
if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s Received misformatted prefixlist ORF. Remove All pfxlist", peer->host);
+ zlog_debug ("%s Received misformatted prefixlist ORF."
+ " Remove All pfxlist", peer->host);
prefix_bgp_orf_remove_all (name);
break;
}
@@ -2276,12 +2291,13 @@ bgp_read_packet (struct peer *peer)
return 0;
/* Read packet from fd. */
- nbytes = stream_read_unblock (peer->ibuf, peer->fd, readsize);
+ nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
/* If read byte is smaller than zero then error occured. */
if (nbytes < 0)
{
- if (errno == EAGAIN)
+ /* Transient error should retry */
+ if (nbytes == -2)
return -1;
plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 189929a0..68d05484 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -137,7 +137,7 @@ static void
bgp_info_free (struct bgp_info *binfo)
{
if (binfo->attr)
- bgp_attr_unintern (binfo->attr);
+ bgp_attr_unintern (&binfo->attr);
bgp_info_extra_free (&binfo->extra);
@@ -1069,11 +1069,9 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
struct bgp_filter *filter;
struct bgp_info info;
struct peer *from;
- struct bgp *bgp;
from = ri->peer;
filter = &rsclient->filter[afi][safi];
- bgp = rsclient->bgp;
if (DISABLE_BGP_ANNOUNCE)
return 0;
@@ -1568,14 +1566,13 @@ bgp_process_queue_init (void)
}
bm->process_main_queue->spec.workfunc = &bgp_process_main;
- bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient;
bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
- bm->process_rsclient_queue->spec.del_item_data
- = bm->process_main_queue->spec.del_item_data;
- bm->process_main_queue->spec.max_retries
- = bm->process_main_queue->spec.max_retries = 0;
- bm->process_rsclient_queue->spec.hold
- = bm->process_main_queue->spec.hold = 50;
+ bm->process_main_queue->spec.max_retries = 0;
+ bm->process_main_queue->spec.hold = 50;
+
+ memcpy (bm->process_rsclient_queue, bm->process_main_queue,
+ sizeof (struct work_queue *));
+ bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient;
}
void
@@ -1803,14 +1800,14 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
/* Apply import policy. */
if (bgp_import_modifier (rsclient, peer, p, &new_attr, afi, safi) == RMAP_DENY)
{
- bgp_attr_unintern (attr_new2);
+ bgp_attr_unintern (&attr_new2);
reason = "import-policy;";
goto filtered;
}
attr_new = bgp_attr_intern (&new_attr);
- bgp_attr_unintern (attr_new2);
+ bgp_attr_unintern (&attr_new2);
/* IPv4 unicast next hop check. */
if (afi == AFI_IP && safi == SAFI_UNICAST)
@@ -1819,7 +1816,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
if (new_attr.nexthop.s_addr == 0
|| IPV4_CLASS_DE (ntohl (new_attr.nexthop.s_addr)))
{
- bgp_attr_unintern (attr_new);
+ bgp_attr_unintern (&attr_new);
reason = "martian next-hop;";
goto filtered;
@@ -1849,7 +1846,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
p->prefixlen, rsclient->host);
bgp_unlock_node (rn);
- bgp_attr_unintern (attr_new);
+ bgp_attr_unintern (&attr_new);
return;
}
@@ -1869,7 +1866,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
/* Update to new attribute. */
- bgp_attr_unintern (ri->attr);
+ bgp_attr_unintern (&ri->attr);
ri->attr = attr_new;
/* Update MPLS tag. */
@@ -2129,7 +2126,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
}
bgp_unlock_node (rn);
- bgp_attr_unintern (attr_new);
+ bgp_attr_unintern (&attr_new);
bgp_attr_extra_free (&new_attr);
return 0;
@@ -2176,7 +2173,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
}
/* Update to new attribute. */
- bgp_attr_unintern (ri->attr);
+ bgp_attr_unintern (&ri->attr);
ri->attr = attr_new;
/* Update MPLS tag. */
@@ -2468,7 +2465,7 @@ bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw)
}
bgp_attr_extra_free (&attr);
- aspath_unintern (aspath);
+ aspath_unintern (&aspath);
}
static void
@@ -3216,7 +3213,7 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
bgp_attr_flush (&attr_tmp);
/* Unintern original. */
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi);
bgp_attr_extra_free (&attr);
@@ -3227,7 +3224,7 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
else
attr_new = bgp_attr_intern (&attr);
- new_attr = *attr_new;
+ bgp_attr_dup(&new_attr, attr_new);
SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
@@ -3243,8 +3240,8 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
bgp->peer_self->rmap_type = 0;
- bgp_attr_unintern (attr_new);
- aspath_unintern (attr.aspath);
+ bgp_attr_unintern (&attr_new);
+ aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi);
@@ -3254,8 +3251,9 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
bgp->peer_self->rmap_type = 0;
- bgp_attr_unintern (attr_new);
+ bgp_attr_unintern (&attr_new);
attr_new = bgp_attr_intern (&new_attr);
+ bgp_attr_extra_free (&new_attr);
for (ri = rn->info; ri; ri = ri->next)
if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
@@ -3268,8 +3266,8 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
{
bgp_unlock_node (rn);
- bgp_attr_unintern (attr_new);
- aspath_unintern (attr.aspath);
+ bgp_attr_unintern (&attr_new);
+ aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
return;
}
@@ -3281,14 +3279,14 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
/* Rewrite BGP route information. */
if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
bgp_info_restore(rn, ri);
- bgp_attr_unintern (ri->attr);
+ bgp_attr_unintern (&ri->attr);
ri->attr = attr_new;
ri->uptime = bgp_clock ();
/* Process change. */
bgp_process (bgp, rn, afi, safi);
bgp_unlock_node (rn);
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
return;
}
@@ -3313,7 +3311,7 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
bgp_process (bgp, rn, afi, safi);
/* Unintern original. */
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
}
@@ -3363,7 +3361,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
bgp_attr_flush (&attr_tmp);
/* Unintern original. */
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
bgp_static_withdraw (bgp, p, afi, safi);
return;
@@ -3384,8 +3382,8 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
{
bgp_unlock_node (rn);
- bgp_attr_unintern (attr_new);
- aspath_unintern (attr.aspath);
+ bgp_attr_unintern (&attr_new);
+ aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
return;
}
@@ -3399,7 +3397,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
bgp_info_restore(rn, ri);
else
bgp_aggregate_decrement (bgp, p, ri, afi, safi);
- bgp_attr_unintern (ri->attr);
+ bgp_attr_unintern (&ri->attr);
ri->attr = attr_new;
ri->uptime = bgp_clock ();
@@ -3407,7 +3405,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
bgp_aggregate_increment (bgp, p, ri, afi, safi);
bgp_process (bgp, rn, afi, safi);
bgp_unlock_node (rn);
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
return;
}
@@ -3435,7 +3433,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
bgp_process (bgp, rn, afi, safi);
/* Unintern original. */
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
}
@@ -4806,9 +4804,8 @@ bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi,
#define AGGREGATE_AS_SET 1
static int
-bgp_aggregate_set (struct vty *vty, const char *prefix_str,
- afi_t afi, safi_t safi,
- u_char summary_only, u_char as_set)
+bgp_aggregate_unset (struct vty *vty, const char *prefix_str,
+ afi_t afi, safi_t safi)
{
int ret;
struct prefix p;
@@ -4829,34 +4826,33 @@ bgp_aggregate_set (struct vty *vty, const char *prefix_str,
bgp = vty->index;
/* Old configuration check. */
- rn = bgp_node_get (bgp->aggregate[afi][safi], &p);
-
- if (rn->info)
+ rn = bgp_node_lookup (bgp->aggregate[afi][safi], &p);
+ if (! rn)
{
- vty_out (vty, "There is already same aggregate network.%s", VTY_NEWLINE);
- bgp_unlock_node (rn);
+ vty_out (vty, "%% There is no aggregate-address configuration.%s",
+ VTY_NEWLINE);
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 = 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);
- /* 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);
+ /* Unlock aggregate address configuration. */
+ rn->info = NULL;
+ bgp_aggregate_free (aggregate);
+ bgp_unlock_node (rn);
+ bgp_unlock_node (rn);
return CMD_SUCCESS;
}
static int
-bgp_aggregate_unset (struct vty *vty, const char *prefix_str,
- afi_t afi, safi_t safi)
+bgp_aggregate_set (struct vty *vty, const char *prefix_str,
+ afi_t afi, safi_t safi,
+ u_char summary_only, u_char as_set)
{
int ret;
struct prefix p;
@@ -4877,25 +4873,33 @@ bgp_aggregate_unset (struct vty *vty, const char *prefix_str,
bgp = vty->index;
/* Old configuration check. */
- rn = bgp_node_lookup (bgp->aggregate[afi][safi], &p);
- if (! rn)
+ rn = bgp_node_get (bgp->aggregate[afi][safi], &p);
+
+ if (rn->info)
{
- vty_out (vty, "%% There is no aggregate-address configuration.%s",
- VTY_NEWLINE);
- return CMD_WARNING;
+ vty_out (vty, "There is already same aggregate network.%s", VTY_NEWLINE);
+ /* try to remove the old entry */
+ ret = bgp_aggregate_unset (vty, prefix_str, afi, safi);
+ if (ret)
+ {
+ vty_out (vty, "Error deleting aggregate.%s", VTY_NEWLINE);
+ bgp_unlock_node (rn);
+ 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);
+ /* Make aggregate address structure. */
+ aggregate = bgp_aggregate_new ();
+ aggregate->summary_only = summary_only;
+ aggregate->as_set = as_set;
+ aggregate->safi = safi;
+ rn->info = aggregate;
- /* Unlock aggregate address configuration. */
- rn->info = NULL;
- bgp_aggregate_free (aggregate);
- bgp_unlock_node (rn);
- bgp_unlock_node (rn);
+ /* 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;
}
@@ -5303,7 +5307,7 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
bgp_attr_extra_free (&attr_new);
/* Unintern original. */
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
bgp_redistribute_delete (p, type);
return;
@@ -5326,8 +5330,8 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
if (attrhash_cmp (bi->attr, new_attr) &&
!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
{
- bgp_attr_unintern (new_attr);
- aspath_unintern (attr.aspath);
+ bgp_attr_unintern (&new_attr);
+ aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
bgp_unlock_node (bn);
return;
@@ -5342,7 +5346,7 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
bgp_info_restore(bn, bi);
else
bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
- bgp_attr_unintern (bi->attr);
+ bgp_attr_unintern (&bi->attr);
bi->attr = new_attr;
bi->uptime = bgp_clock ();
@@ -5350,7 +5354,7 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST);
bgp_process (bgp, bn, afi, SAFI_UNICAST);
bgp_unlock_node (bn);
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
return;
}
@@ -5372,7 +5376,7 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
}
/* Unintern original. */
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
}
@@ -6381,7 +6385,10 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
if ((rm = bgp_node_match (table, &match)) != NULL)
{
if (prefix_check && rm->p.prefixlen != match.prefixlen)
- continue;
+ {
+ bgp_unlock_node (rm);
+ continue;
+ }
for (ri = rm->info; ri; ri = ri->next)
{
@@ -6395,6 +6402,8 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
display++;
route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, SAFI_MPLS_VPN);
}
+
+ bgp_unlock_node (rm);
}
}
}
@@ -6418,6 +6427,8 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi);
}
}
+
+ bgp_unlock_node (rn);
}
}
@@ -6490,6 +6501,15 @@ DEFUN (show_ip_bgp_ipv4,
return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_normal, NULL);
}
+ALIAS (show_ip_bgp_ipv4,
+ show_bgp_ipv4_safi_cmd,
+ "show bgp ipv4 (unicast|multicast)",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n")
+
DEFUN (show_ip_bgp_route,
show_ip_bgp_route_cmd,
"show ip bgp A.B.C.D",
@@ -6518,6 +6538,16 @@ DEFUN (show_ip_bgp_ipv4_route,
return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0);
}
+ALIAS (show_ip_bgp_ipv4_route,
+ show_bgp_ipv4_safi_route_cmd,
+ "show bgp ipv4 (unicast|multicast) A.B.C.D",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Network in the BGP routing table to display\n")
+
DEFUN (show_ip_bgp_vpnv4_all_route,
show_ip_bgp_vpnv4_all_route_cmd,
"show ip bgp vpnv4 all A.B.C.D",
@@ -6582,6 +6612,16 @@ DEFUN (show_ip_bgp_ipv4_prefix,
return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1);
}
+ALIAS (show_ip_bgp_ipv4_prefix,
+ show_bgp_ipv4_safi_prefix_cmd,
+ "show bgp ipv4 (unicast|multicast) A.B.C.D/M",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+
DEFUN (show_ip_bgp_vpnv4_all_prefix,
show_ip_bgp_vpnv4_all_prefix_cmd,
"show ip bgp vpnv4 all A.B.C.D/M",
@@ -6684,6 +6724,22 @@ ALIAS (show_bgp,
BGP_STR
"Address family\n")
+DEFUN (show_bgp_ipv6_safi,
+ show_bgp_ipv6_safi_cmd,
+ "show bgp ipv6 (unicast|multicast)",
+ SHOW_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_IP6, SAFI_MULTICAST, bgp_show_type_normal,
+ NULL);
+
+ return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST, bgp_show_type_normal, NULL);
+}
+
/* old command */
DEFUN (show_ipv6_bgp,
show_ipv6_bgp_cmd,
@@ -6714,6 +6770,22 @@ ALIAS (show_bgp_route,
"Address family\n"
"Network in the BGP routing table to display\n")
+DEFUN (show_bgp_ipv6_safi_route,
+ show_bgp_ipv6_safi_route_cmd,
+ "show bgp ipv6 (unicast|multicast) X:X::X:X",
+ SHOW_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_IP6, SAFI_MULTICAST, NULL, 0);
+
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0);
+}
+
/* old command */
DEFUN (show_ipv6_bgp_route,
show_ipv6_bgp_route_cmd,
@@ -6744,6 +6816,22 @@ ALIAS (show_bgp_prefix,
"Address family\n"
"IPv6 prefix <network>/<length>\n")
+DEFUN (show_bgp_ipv6_safi_prefix,
+ show_bgp_ipv6_safi_prefix_cmd,
+ "show bgp ipv6 (unicast|multicast) X:X::X:X/M",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
+{
+ if (strncmp (argv[0], "m", 1) == 0)
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 1);
+
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1);
+}
+
/* old command */
DEFUN (show_ipv6_bgp_prefix,
show_ipv6_bgp_prefix_cmd,
@@ -7448,15 +7536,36 @@ DEFUN (show_ipv6_mbgp_community_all,
#endif /* HAVE_IPV6 */
static int
-bgp_show_community (struct vty *vty, int argc, const char **argv, int exact,
- afi_t afi, safi_t safi)
+bgp_show_community (struct vty *vty, const char *view_name, int argc,
+ const char **argv, int exact, afi_t afi, safi_t safi)
{
struct community *com;
struct buffer *b;
+ struct bgp *bgp;
int i;
char *str;
int first = 0;
+ /* 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;
+ }
+ }
+
b = buffer_new (1024);
for (i = 0; i < argc; i++)
{
@@ -7484,7 +7593,7 @@ bgp_show_community (struct vty *vty, int argc, const char **argv, int exact,
return CMD_WARNING;
}
- return bgp_show (vty, NULL, afi, safi,
+ return bgp_show (vty, bgp, afi, safi,
(exact ? bgp_show_type_community_exact :
bgp_show_type_community), com);
}
@@ -7501,7 +7610,7 @@ DEFUN (show_ip_bgp_community,
"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);
+ return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_UNICAST);
}
ALIAS (show_ip_bgp_community,
@@ -7580,9 +7689,9 @@ DEFUN (show_ip_bgp_ipv4_community,
"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, NULL, argc, argv, 0, AFI_IP, SAFI_MULTICAST);
- return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_UNICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_UNICAST);
}
ALIAS (show_ip_bgp_ipv4_community,
@@ -7654,6 +7763,177 @@ ALIAS (show_ip_bgp_ipv4_community,
"Do not advertise to any peer (well-known community)\n"
"Do not export to next AS (well-known community)\n")
+DEFUN (show_bgp_view_afi_safi_community_all,
+ show_bgp_view_afi_safi_community_all_cmd,
+#ifdef HAVE_IPV6
+ "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community",
+#else
+ "show bgp view WORD ipv4 (unicast|multicast) community",
+#endif
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+#ifdef HAVE_IPV6
+ "Address family\n"
+#endif
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Display routes containing communities\n")
+{
+ int afi;
+ int safi;
+ struct bgp *bgp;
+
+ /* BGP structure lookup. */
+ bgp = bgp_lookup_by_name (argv[0]);
+ if (bgp == NULL)
+ {
+ vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+#ifdef HAVE_IPV6
+ afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
+ safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+#else
+ afi = AFI_IP;
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+#endif
+ return bgp_show (vty, bgp, afi, safi, bgp_show_type_community_all, NULL);
+}
+
+DEFUN (show_bgp_view_afi_safi_community,
+ show_bgp_view_afi_safi_community_cmd,
+#ifdef HAVE_IPV6
+ "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)",
+#else
+ "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)",
+#endif
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+#ifdef HAVE_IPV6
+ "Address family\n"
+#endif
+ "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")
+{
+ int afi;
+ int safi;
+
+#ifdef HAVE_IPV6
+ afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
+ safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ return bgp_show_community (vty, argv[0], argc-3, &argv[3], 0, afi, safi);
+#else
+ afi = AFI_IP;
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ return bgp_show_community (vty, argv[0], argc-2, &argv[2], 0, afi, safi);
+#endif
+}
+
+ALIAS (show_bgp_view_afi_safi_community,
+ show_bgp_view_afi_safi_community2_cmd,
+#ifdef HAVE_IPV6
+ "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#else
+ "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#endif
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+#ifdef HAVE_IPV6
+ "Address family\n"
+#endif
+ "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_bgp_view_afi_safi_community,
+ show_bgp_view_afi_safi_community3_cmd,
+#ifdef HAVE_IPV6
+ "show bgp view WORD (ipv4|ipv6) (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)",
+#else
+ "show bgp view WORD 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)",
+#endif
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+#ifdef HAVE_IPV6
+ "Address family\n"
+#endif
+ "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_bgp_view_afi_safi_community,
+ show_bgp_view_afi_safi_community4_cmd,
+#ifdef HAVE_IPV6
+ "show bgp view WORD (ipv4|ipv6) (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)",
+#else
+ "show bgp view WORD 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)",
+#endif
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+#ifdef HAVE_IPV6
+ "Address family\n"
+#endif
+ "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",
@@ -7667,7 +7947,7 @@ DEFUN (show_ip_bgp_community_exact,
"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);
+ return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_UNICAST);
}
ALIAS (show_ip_bgp_community_exact,
@@ -7750,9 +8030,9 @@ DEFUN (show_ip_bgp_ipv4_community_exact,
"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, NULL, argc, argv, 1, AFI_IP, SAFI_MULTICAST);
- return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_UNICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_UNICAST);
}
ALIAS (show_ip_bgp_ipv4_community_exact,
@@ -7839,7 +8119,7 @@ DEFUN (show_bgp_community,
"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);
+ return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
}
ALIAS (show_bgp_community,
@@ -7984,7 +8264,7 @@ DEFUN (show_ipv6_bgp_community,
"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);
+ return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
}
/* old command */
@@ -8062,7 +8342,7 @@ DEFUN (show_bgp_community_exact,
"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);
+ return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
}
ALIAS (show_bgp_community_exact,
@@ -8215,7 +8495,7 @@ DEFUN (show_ipv6_bgp_community_exact,
"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);
+ return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
}
/* old command */
@@ -8297,7 +8577,7 @@ DEFUN (show_ipv6_mbgp_community,
"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);
+ return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_MULTICAST);
}
/* old command */
@@ -8377,7 +8657,7 @@ DEFUN (show_ipv6_mbgp_community_exact,
"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);
+ return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_MULTICAST);
}
/* old command */
@@ -9777,6 +10057,56 @@ DEFUN (show_ip_bgp_ipv4_neighbor_received_routes,
return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 1);
}
+DEFUN (show_bgp_view_afi_safi_neighbor_adv_recd_routes,
+ show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd,
+#ifdef HAVE_IPV6
+ "show bgp view WORD (ipv4|ipv6) (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) (advertised-routes|received-routes)",
+#else
+ "show bgp view WORD ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) (advertised-routes|received-routes)",
+#endif
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+#ifdef HAVE_IPV6
+ "Address family\n"
+#endif
+ "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 advertised routes to neighbor\n"
+ "Display the received routes from neighbor\n")
+{
+ int afi;
+ int safi;
+ int in;
+ struct peer *peer;
+
+#ifdef HAVE_IPV6
+ peer = peer_lookup_in_view (vty, argv[0], argv[3]);
+#else
+ peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+#endif
+
+ if (! peer)
+ return CMD_WARNING;
+
+#ifdef HAVE_IPV6
+ afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
+ safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ in = (strncmp (argv[4], "r", 1) == 0) ? 1 : 0;
+#else
+ afi = AFI_IP;
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ in = (strncmp (argv[3], "r", 1) == 0) ? 1 : 0;
+#endif
+
+ return peer_adj_routes (vty, peer, afi, safi, in);
+}
+
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",
@@ -10184,6 +10514,65 @@ ALIAS (show_ip_bgp_view_rsclient,
"Information about Route Server Client\n"
NEIGHBOR_ADDR_STR)
+DEFUN (show_bgp_view_ipv4_safi_rsclient,
+ show_bgp_view_ipv4_safi_rsclient_cmd,
+ "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR)
+{
+ struct bgp_table *table;
+ struct peer *peer;
+ safi_t safi;
+
+ if (argc == 3) {
+ peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ } else {
+ peer = peer_lookup_in_view (vty, NULL, argv[1]);
+ safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ }
+
+ if (! peer)
+ return CMD_WARNING;
+
+ if (! peer->afc[AFI_IP][safi])
+ {
+ vty_out (vty, "%% Activate the neighbor for the address family first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+ {
+ vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ table = peer->rib[AFI_IP][safi];
+
+ return bgp_show_table (vty, table, &peer->remote_id, bgp_show_type_normal, NULL);
+}
+
+ALIAS (show_bgp_view_ipv4_safi_rsclient,
+ show_bgp_ipv4_safi_rsclient_cmd,
+ "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR)
+
DEFUN (show_ip_bgp_view_rsclient_route,
show_ip_bgp_view_rsclient_route_cmd,
"show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X) A.B.C.D",
@@ -10257,6 +10646,87 @@ ALIAS (show_ip_bgp_view_rsclient_route,
NEIGHBOR_ADDR_STR
"Network in the BGP routing table to display\n")
+DEFUN (show_bgp_view_ipv4_safi_rsclient_route,
+ show_bgp_view_ipv4_safi_rsclient_route_cmd,
+ "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "Network in the BGP routing table to display\n")
+{
+ struct bgp *bgp;
+ struct peer *peer;
+ safi_t safi;
+
+ /* BGP structure lookup. */
+ if (argc == 4)
+ {
+ bgp = bgp_lookup_by_name (argv[0]);
+ if (bgp == NULL)
+ {
+ vty_out (vty, "Can't find BGP view %s%s", argv[0], 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;
+ }
+ }
+
+ if (argc == 4) {
+ peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ } else {
+ peer = peer_lookup_in_view (vty, NULL, argv[1]);
+ safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ }
+
+ if (! peer)
+ return CMD_WARNING;
+
+ if (! peer->afc[AFI_IP][safi])
+ {
+ vty_out (vty, "%% Activate the neighbor for the address family first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+}
+
+ if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+ {
+ vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][safi],
+ (argc == 4) ? argv[3] : argv[2],
+ AFI_IP, safi, NULL, 0);
+}
+
+ALIAS (show_bgp_view_ipv4_safi_rsclient_route,
+ show_bgp_ipv4_safi_rsclient_route_cmd,
+ "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "Network in the BGP routing table to display\n")
+
DEFUN (show_ip_bgp_view_rsclient_prefix,
show_ip_bgp_view_rsclient_prefix_cmd,
"show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
@@ -10330,6 +10800,86 @@ ALIAS (show_ip_bgp_view_rsclient_prefix,
NEIGHBOR_ADDR_STR
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+DEFUN (show_bgp_view_ipv4_safi_rsclient_prefix,
+ show_bgp_view_ipv4_safi_rsclient_prefix_cmd,
+ "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+ struct bgp *bgp;
+ struct peer *peer;
+ safi_t safi;
+
+ /* BGP structure lookup. */
+ if (argc == 4)
+ {
+ bgp = bgp_lookup_by_name (argv[0]);
+ if (bgp == NULL)
+ {
+ vty_out (vty, "Can't find BGP view %s%s", argv[0], 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;
+ }
+ }
+
+ if (argc == 4) {
+ peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ } else {
+ peer = peer_lookup_in_view (vty, NULL, argv[1]);
+ safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ }
+
+ if (! peer)
+ return CMD_WARNING;
+
+ if (! peer->afc[AFI_IP][safi])
+ {
+ vty_out (vty, "%% Activate the neighbor for the address family first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+}
+
+ if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+{
+ vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][safi],
+ (argc == 4) ? argv[3] : argv[2],
+ AFI_IP, safi, NULL, 1);
+}
+
+ALIAS (show_bgp_view_ipv4_safi_rsclient_prefix,
+ show_bgp_ipv4_safi_rsclient_prefix_cmd,
+ "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
#ifdef HAVE_IPV6
DEFUN (show_bgp_view_neighbor_routes,
@@ -10596,6 +11146,65 @@ ALIAS (show_bgp_view_rsclient,
"Information about Route Server Client\n"
NEIGHBOR_ADDR_STR)
+DEFUN (show_bgp_view_ipv6_safi_rsclient,
+ show_bgp_view_ipv6_safi_rsclient_cmd,
+ "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR)
+{
+ struct bgp_table *table;
+ struct peer *peer;
+ safi_t safi;
+
+ if (argc == 3) {
+ peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ } else {
+ peer = peer_lookup_in_view (vty, NULL, argv[1]);
+ safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ }
+
+ if (! peer)
+ return CMD_WARNING;
+
+ if (! peer->afc[AFI_IP6][safi])
+ {
+ vty_out (vty, "%% Activate the neighbor for the address family first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+ {
+ vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ table = peer->rib[AFI_IP6][safi];
+
+ return bgp_show_table (vty, table, &peer->remote_id, bgp_show_type_normal, NULL);
+}
+
+ALIAS (show_bgp_view_ipv6_safi_rsclient,
+ show_bgp_ipv6_safi_rsclient_cmd,
+ "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR)
+
DEFUN (show_bgp_view_rsclient_route,
show_bgp_view_rsclient_route_cmd,
"show bgp view WORD rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
@@ -10667,6 +11276,87 @@ ALIAS (show_bgp_view_rsclient_route,
NEIGHBOR_ADDR_STR
"Network in the BGP routing table to display\n")
+DEFUN (show_bgp_view_ipv6_safi_rsclient_route,
+ show_bgp_view_ipv6_safi_rsclient_route_cmd,
+ "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "Network in the BGP routing table to display\n")
+{
+ struct bgp *bgp;
+ struct peer *peer;
+ safi_t safi;
+
+ /* BGP structure lookup. */
+ if (argc == 4)
+ {
+ bgp = bgp_lookup_by_name (argv[0]);
+ if (bgp == NULL)
+ {
+ vty_out (vty, "Can't find BGP view %s%s", argv[0], 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;
+ }
+ }
+
+ if (argc == 4) {
+ peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ } else {
+ peer = peer_lookup_in_view (vty, NULL, argv[1]);
+ safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ }
+
+ if (! peer)
+ return CMD_WARNING;
+
+ if (! peer->afc[AFI_IP6][safi])
+ {
+ vty_out (vty, "%% Activate the neighbor for the address family first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+}
+
+ if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+ {
+ vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][safi],
+ (argc == 4) ? argv[3] : argv[2],
+ AFI_IP6, safi, NULL, 0);
+}
+
+ALIAS (show_bgp_view_ipv6_safi_rsclient_route,
+ show_bgp_ipv6_safi_rsclient_route_cmd,
+ "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "Network in the BGP routing table to display\n")
+
DEFUN (show_bgp_view_rsclient_prefix,
show_bgp_view_rsclient_prefix_cmd,
"show bgp view WORD rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
@@ -10738,6 +11428,87 @@ ALIAS (show_bgp_view_rsclient_prefix,
NEIGHBOR_ADDR_STR
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
+DEFUN (show_bgp_view_ipv6_safi_rsclient_prefix,
+ show_bgp_view_ipv6_safi_rsclient_prefix_cmd,
+ "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "IP prefix <network>/<length>, e.g., 3ffe::/16\n")
+{
+ struct bgp *bgp;
+ struct peer *peer;
+ safi_t safi;
+
+ /* BGP structure lookup. */
+ if (argc == 4)
+ {
+ bgp = bgp_lookup_by_name (argv[0]);
+ if (bgp == NULL)
+ {
+ vty_out (vty, "Can't find BGP view %s%s", argv[0], 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;
+ }
+ }
+
+ if (argc == 4) {
+ peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ } else {
+ peer = peer_lookup_in_view (vty, NULL, argv[1]);
+ safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ }
+
+ if (! peer)
+ return CMD_WARNING;
+
+ if (! peer->afc[AFI_IP6][safi])
+ {
+ vty_out (vty, "%% Activate the neighbor for the address family first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+}
+
+ if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+{
+ vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][safi],
+ (argc == 4) ? argv[3] : argv[2],
+ AFI_IP6, safi, NULL, 1);
+}
+
+ALIAS (show_bgp_view_ipv6_safi_rsclient_prefix,
+ show_bgp_ipv6_safi_rsclient_prefix_cmd,
+ "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "IP prefix <network>/<length>, e.g., 3ffe::/16\n")
+
#endif /* HAVE_IPV6 */
struct bgp_table *bgp_distance_table;
@@ -11166,41 +11937,49 @@ bgp_clear_damp_route (struct vty *vty, const char *view_name,
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->extra && ri->extra->damp_info)
- {
- ri_temp = ri->next;
- bgp_damp_info_free (ri->extra->damp_info, 1);
- ri = ri_temp;
- }
- else
- ri = ri->next;
- }
- }
+ {
+ if (! prefix_check || rm->p.prefixlen == match.prefixlen)
+ {
+ ri = rm->info;
+ while (ri)
+ {
+ if (ri->extra && ri->extra->damp_info)
+ {
+ ri_temp = ri->next;
+ bgp_damp_info_free (ri->extra->damp_info, 1);
+ ri = ri_temp;
+ }
+ else
+ ri = ri->next;
+ }
+ }
+
+ bgp_unlock_node (rm);
+ }
}
}
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->extra && ri->extra->damp_info)
- {
- ri_temp = ri->next;
- bgp_damp_info_free (ri->extra->damp_info, 1);
- ri = ri_temp;
- }
- else
- ri = ri->next;
- }
- }
+ {
+ if (! prefix_check || rn->p.prefixlen == match.prefixlen)
+ {
+ ri = rn->info;
+ while (ri)
+ {
+ if (ri->extra && ri->extra->damp_info)
+ {
+ ri_temp = ri->next;
+ bgp_damp_info_free (ri->extra->damp_info, 1);
+ ri = ri_temp;
+ }
+ else
+ ri = ri->next;
+ }
+ }
+
+ bgp_unlock_node (rn);
+ }
}
return CMD_SUCCESS;
@@ -11555,12 +12334,15 @@ bgp_route_init (void)
install_element (VIEW_NODE, &show_ip_bgp_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_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_bgp_ipv4_safi_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_bgp_ipv4_safi_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);
@@ -11586,6 +12368,11 @@ bgp_route_init (void)
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_bgp_view_afi_safi_community_all_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_afi_safi_community_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_afi_safi_community2_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_afi_safi_community3_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_afi_safi_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);
@@ -11604,6 +12391,7 @@ bgp_route_init (void)
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_bgp_view_afi_safi_neighbor_adv_recd_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);
@@ -11621,20 +12409,28 @@ bgp_route_init (void)
install_element (VIEW_NODE, &show_ip_bgp_neighbor_flap_cmd);
install_element (VIEW_NODE, &show_ip_bgp_neighbor_damp_cmd);
install_element (VIEW_NODE, &show_ip_bgp_rsclient_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_cmd);
install_element (VIEW_NODE, &show_ip_bgp_rsclient_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd);
install_element (VIEW_NODE, &show_ip_bgp_rsclient_prefix_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd);
install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_advertised_route_cmd);
install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_received_routes_cmd);
install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_cmd);
install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd);
install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_prefix_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd);
/* Restricted node: VIEW_NODE - (set of dangerous commands) */
install_element (RESTRICTED_NODE, &show_ip_bgp_route_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_route_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_route_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_prefix_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_prefix_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_view_route_cmd);
@@ -11647,6 +12443,11 @@ bgp_route_init (void)
install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community2_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community3_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community4_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community_all_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community2_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community3_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community4_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_community_exact_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_community2_exact_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_community3_exact_cmd);
@@ -11656,18 +12457,25 @@ bgp_route_init (void)
install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community3_exact_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community4_exact_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_rsclient_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_rsclient_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_view_rsclient_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_view_rsclient_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_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_bgp_ipv4_safi_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_bgp_ipv4_safi_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);
@@ -11693,6 +12501,11 @@ bgp_route_init (void)
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_bgp_view_afi_safi_community_all_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community2_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community3_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_afi_safi_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);
@@ -11711,6 +12524,7 @@ bgp_route_init (void)
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_bgp_view_afi_safi_neighbor_adv_recd_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);
@@ -11728,13 +12542,19 @@ bgp_route_init (void)
install_element (ENABLE_NODE, &show_ip_bgp_neighbor_flap_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_neighbor_damp_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_rsclient_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_rsclient_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_rsclient_prefix_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_advertised_route_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_received_routes_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_prefix_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd);
/* BGP dampening clear commands */
install_element (ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
@@ -11771,10 +12591,13 @@ bgp_route_init (void)
install_element (VIEW_NODE, &show_bgp_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_cmd);
install_element (VIEW_NODE, &show_bgp_route_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_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_ipv6_safi_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);
@@ -11820,8 +12643,11 @@ bgp_route_init (void)
install_element (VIEW_NODE, &show_bgp_neighbor_damp_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_damp_cmd);
install_element (VIEW_NODE, &show_bgp_rsclient_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_cmd);
install_element (VIEW_NODE, &show_bgp_rsclient_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd);
install_element (VIEW_NODE, &show_bgp_rsclient_prefix_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd);
install_element (VIEW_NODE, &show_bgp_view_cmd);
install_element (VIEW_NODE, &show_bgp_view_ipv6_cmd);
install_element (VIEW_NODE, &show_bgp_view_route_cmd);
@@ -11841,16 +12667,21 @@ bgp_route_init (void)
install_element (VIEW_NODE, &show_bgp_view_neighbor_damp_cmd);
install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_damp_cmd);
install_element (VIEW_NODE, &show_bgp_view_rsclient_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_cmd);
install_element (VIEW_NODE, &show_bgp_view_rsclient_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd);
install_element (VIEW_NODE, &show_bgp_view_rsclient_prefix_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd);
/* Restricted:
* VIEW_NODE - (set of dangerous commands) - (commands dependent on prev)
*/
install_element (RESTRICTED_NODE, &show_bgp_route_cmd);
install_element (RESTRICTED_NODE, &show_bgp_ipv6_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_route_cmd);
install_element (RESTRICTED_NODE, &show_bgp_prefix_cmd);
install_element (RESTRICTED_NODE, &show_bgp_ipv6_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_prefix_cmd);
install_element (RESTRICTED_NODE, &show_bgp_community_cmd);
install_element (RESTRICTED_NODE, &show_bgp_ipv6_community_cmd);
install_element (RESTRICTED_NODE, &show_bgp_community2_cmd);
@@ -11868,7 +12699,9 @@ bgp_route_init (void)
install_element (RESTRICTED_NODE, &show_bgp_community4_exact_cmd);
install_element (RESTRICTED_NODE, &show_bgp_ipv6_community4_exact_cmd);
install_element (RESTRICTED_NODE, &show_bgp_rsclient_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd);
install_element (RESTRICTED_NODE, &show_bgp_rsclient_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd);
install_element (RESTRICTED_NODE, &show_bgp_view_route_cmd);
install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_route_cmd);
install_element (RESTRICTED_NODE, &show_bgp_view_prefix_cmd);
@@ -11876,14 +12709,19 @@ bgp_route_init (void)
install_element (RESTRICTED_NODE, &show_bgp_view_neighbor_received_prefix_filter_cmd);
install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_neighbor_received_prefix_filter_cmd);
install_element (RESTRICTED_NODE, &show_bgp_view_rsclient_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd);
install_element (RESTRICTED_NODE, &show_bgp_view_rsclient_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd);
install_element (ENABLE_NODE, &show_bgp_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_cmd);
install_element (ENABLE_NODE, &show_bgp_route_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_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_ipv6_safi_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);
@@ -11929,8 +12767,11 @@ bgp_route_init (void)
install_element (ENABLE_NODE, &show_bgp_neighbor_damp_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_damp_cmd);
install_element (ENABLE_NODE, &show_bgp_rsclient_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_cmd);
install_element (ENABLE_NODE, &show_bgp_rsclient_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd);
install_element (ENABLE_NODE, &show_bgp_rsclient_prefix_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd);
install_element (ENABLE_NODE, &show_bgp_view_cmd);
install_element (ENABLE_NODE, &show_bgp_view_ipv6_cmd);
install_element (ENABLE_NODE, &show_bgp_view_route_cmd);
@@ -11950,8 +12791,11 @@ bgp_route_init (void)
install_element (ENABLE_NODE, &show_bgp_view_neighbor_damp_cmd);
install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_damp_cmd);
install_element (ENABLE_NODE, &show_bgp_view_rsclient_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_cmd);
install_element (ENABLE_NODE, &show_bgp_view_rsclient_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd);
install_element (ENABLE_NODE, &show_bgp_view_rsclient_prefix_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd);
/* Statistics */
install_element (ENABLE_NODE, &show_bgp_statistics_cmd);
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 42c3e053..abb85fd2 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -1470,6 +1470,13 @@ route_set_community_delete (void *rule, struct prefix *prefix,
new = community_uniq_sort (merge);
community_free (merge);
+ /* HACK: if the old community is not intern'd,
+ * we should free it here, or all reference to it may be lost.
+ * Really need to cleanup attribute caching sometime.
+ */
+ if (old->refcnt == 0)
+ community_free (old);
+
if (new->size == 0)
{
binfo->attr->community = NULL;
@@ -1552,10 +1559,10 @@ route_set_ecommunity_rt (void *rule, struct prefix *prefix,
else
new_ecom = ecommunity_dup (ecom);
- bgp_info->attr->extra->ecommunity = new_ecom;
+ bgp_info->attr->extra->ecommunity = ecommunity_intern (new_ecom);
if (old_ecom)
- ecommunity_free (old_ecom);
+ ecommunity_unintern (&old_ecom);
bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
}
@@ -1571,7 +1578,7 @@ route_set_ecommunity_rt_compile (const char *arg)
ecom = ecommunity_str2com (arg, ECOMMUNITY_ROUTE_TARGET, 0);
if (! ecom)
return NULL;
- return ecom;
+ return ecommunity_intern (ecom);
}
/* Free function for set community. */
@@ -1579,7 +1586,7 @@ static void
route_set_ecommunity_rt_free (void *rule)
{
struct ecommunity *ecom = rule;
- ecommunity_free (ecom);
+ ecommunity_unintern (&ecom);
}
/* Set community rule structure. */
@@ -1598,7 +1605,7 @@ static route_map_result_t
route_set_ecommunity_soo (void *rule, struct prefix *prefix,
route_map_object_t type, void *object)
{
- struct ecommunity *ecom;
+ struct ecommunity *ecom, *old_ecom, *new_ecom;
struct bgp_info *bgp_info;
if (type == RMAP_BGP)
@@ -1609,8 +1616,19 @@ route_set_ecommunity_soo (void *rule, struct prefix *prefix,
if (! ecom)
return RMAP_OKAY;
+ old_ecom = (bgp_attr_extra_get (bgp_info->attr))->ecommunity;
+
+ if (old_ecom)
+ new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom);
+ else
+ new_ecom = ecommunity_dup (ecom);
+
+ bgp_info->attr->extra->ecommunity = ecommunity_intern (new_ecom);
+
+ if (old_ecom)
+ ecommunity_unintern (&old_ecom);
+
bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
- (bgp_attr_extra_get (bgp_info->attr))->ecommunity = ecommunity_dup (ecom);
}
return RMAP_OKAY;
}
@@ -1625,7 +1643,7 @@ route_set_ecommunity_soo_compile (const char *arg)
if (! ecom)
return NULL;
- return ecom;
+ return ecommunity_intern (ecom);
}
/* Free function for set community. */
@@ -1633,7 +1651,7 @@ static void
route_set_ecommunity_soo_free (void *rule)
{
struct ecommunity *ecom = rule;
- ecommunity_free (ecom);
+ ecommunity_unintern (&ecom);
}
/* Set community rule structure. */
diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c
index 91cab606..a249c23d 100644
--- a/bgpd/bgp_table.c
+++ b/bgpd/bgp_table.c
@@ -350,7 +350,6 @@ bgp_node_get (struct bgp_table *const table, struct prefix *p)
if (new->p.prefixlen != p->prefixlen)
{
match = new;
- bgp_lock_node (match);
new = bgp_node_set (table, p);
set_link (match, new);
table->count++;
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 9cb30182..f65bb157 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -213,6 +213,12 @@ bgp_vty_return (struct vty *vty, int ret)
case BGP_ERR_TCPSIG_FAILED:
str = "Error while applying TCP-Sig to session(s)";
break;
+ case BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK:
+ str = "ebgp-multihop and ttl-security cannot be configured together";
+ break;
+ case BGP_ERR_NO_IBGP_WITH_TTLHACK:
+ str = "ttl-security only allowed for EBGP peers";
+ break;
}
if (str)
{
@@ -2636,9 +2642,7 @@ peer_ebgp_multihop_set_vty (struct vty *vty, const char *ip_str,
else
VTY_GET_INTEGER_RANGE ("TTL", ttl, ttl_str, 1, 255);
- peer_ebgp_multihop_set (peer, ttl);
-
- return CMD_SUCCESS;
+ return bgp_vty_return (vty, peer_ebgp_multihop_set (peer, ttl));
}
static int
@@ -2650,9 +2654,7 @@ peer_ebgp_multihop_unset_vty (struct vty *vty, const char *ip_str)
if (! peer)
return CMD_WARNING;
- peer_ebgp_multihop_unset (peer);
-
- return CMD_SUCCESS;
+ return bgp_vty_return (vty, peer_ebgp_multihop_unset (peer));
}
/* neighbor ebgp-multihop. */
@@ -3954,6 +3956,42 @@ DEFUN (no_neighbor_allowas_in,
return bgp_vty_return (vty, ret);
}
+DEFUN (neighbor_ttl_security,
+ neighbor_ttl_security_cmd,
+ NEIGHBOR_CMD2 "ttl-security hops <1-254>",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Specify the maximum number of hops to the BGP peer\n")
+{
+ struct peer *peer;
+ int gtsm_hops;
+
+ peer = peer_and_group_lookup_vty (vty, argv[0]);
+ if (! peer)
+ return CMD_WARNING;
+
+ VTY_GET_INTEGER_RANGE ("", gtsm_hops, argv[1], 1, 254);
+
+ return bgp_vty_return (vty, peer_ttl_security_hops_set (peer, gtsm_hops));
+}
+
+DEFUN (no_neighbor_ttl_security,
+ no_neighbor_ttl_security_cmd,
+ NO_NEIGHBOR_CMD2 "ttl-security hops <1-254>",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Specify the maximum number of hops to the BGP peer\n")
+{
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty (vty, argv[0]);
+ if (! peer)
+ return CMD_WARNING;
+
+ return bgp_vty_return (vty, peer_ttl_security_hops_unset (peer));
+}
+
/* Address family configuration. */
DEFUN (address_family_ipv4,
address_family_ipv4_cmd,
@@ -6856,6 +6894,16 @@ DEFUN (show_ip_bgp_ipv4_summary,
return bgp_show_summary_vty (vty, NULL, AFI_IP, SAFI_UNICAST);
}
+ALIAS (show_ip_bgp_ipv4_summary,
+ show_bgp_ipv4_safi_summary_cmd,
+ "show bgp ipv4 (unicast|multicast) summary",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Summary of BGP neighbor status\n")
+
DEFUN (show_ip_bgp_instance_ipv4_summary,
show_ip_bgp_instance_ipv4_summary_cmd,
"show ip bgp view WORD ipv4 (unicast|multicast) summary",
@@ -6875,6 +6923,18 @@ DEFUN (show_ip_bgp_instance_ipv4_summary,
return bgp_show_summary_vty (vty, argv[0], AFI_IP, SAFI_UNICAST);
}
+ALIAS (show_ip_bgp_instance_ipv4_summary,
+ show_bgp_instance_ipv4_safi_summary_cmd,
+ "show bgp view WORD ipv4 (unicast|multicast) summary",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "View name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Summary of BGP neighbor status\n")
+
DEFUN (show_ip_bgp_vpnv4_all_summary,
show_ip_bgp_vpnv4_all_summary_cmd,
"show ip bgp vpnv4 all summary",
@@ -6953,6 +7013,40 @@ ALIAS (show_bgp_instance_summary,
"Address family\n"
"Summary of BGP neighbor status\n")
+DEFUN (show_bgp_ipv6_safi_summary,
+ show_bgp_ipv6_safi_summary_cmd,
+ "show bgp ipv6 (unicast|multicast) summary",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Summary of BGP neighbor status\n")
+{
+ if (strncmp (argv[0], "m", 1) == 0)
+ return bgp_show_summary_vty (vty, NULL, AFI_IP6, SAFI_MULTICAST);
+
+ return bgp_show_summary_vty (vty, NULL, AFI_IP6, SAFI_UNICAST);
+}
+
+DEFUN (show_bgp_instance_ipv6_safi_summary,
+ show_bgp_instance_ipv6_safi_summary_cmd,
+ "show bgp view WORD ipv6 (unicast|multicast) summary",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "View name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Summary of BGP neighbor status\n")
+{
+ if (strncmp (argv[1], "m", 1) == 0)
+ return bgp_show_summary_vty (vty, argv[0], AFI_IP6, SAFI_MULTICAST);
+
+ return bgp_show_summary_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST);
+}
+
/* old command */
DEFUN (show_ipv6_bgp_summary,
show_ipv6_bgp_summary_cmd,
@@ -7544,10 +7638,16 @@ bgp_show_peer (struct vty *vty, struct peer *p)
p->host, VTY_NEWLINE);
}
- /* EBGP Multihop */
- if (peer_sort (p) != BGP_PEER_IBGP && p->ttl > 1)
- vty_out (vty, " External BGP neighbor may be up to %d hops away.%s",
- p->ttl, VTY_NEWLINE);
+ /* EBGP Multihop and GTSM */
+ if (peer_sort (p) != BGP_PEER_IBGP)
+ {
+ if (p->gtsm_hops > 0)
+ vty_out (vty, " External BGP neighbor may be up to %d hops away.%s",
+ p->gtsm_hops, VTY_NEWLINE);
+ else if (p->ttl > 1)
+ vty_out (vty, " External BGP neighbor may be up to %d hops away.%s",
+ p->ttl, VTY_NEWLINE);
+ }
/* Local address. */
if (p->su_local)
@@ -8154,6 +8254,41 @@ DEFUN (show_ip_bgp_instance_ipv4_rsclient_summary,
return bgp_show_rsclient_summary_vty (vty, argv[0], AFI_IP, SAFI_UNICAST);
}
+DEFUN (show_bgp_instance_ipv4_safi_rsclient_summary,
+ show_bgp_instance_ipv4_safi_rsclient_summary_cmd,
+ "show bgp view WORD ipv4 (unicast|multicast) rsclient summary",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "View name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Clients\n"
+ "Summary of all Route Server Clients\n")
+{
+ safi_t safi;
+
+ if (argc == 2) {
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ return bgp_show_rsclient_summary_vty (vty, argv[0], AFI_IP, safi);
+ } else {
+ safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ return bgp_show_rsclient_summary_vty (vty, NULL, AFI_IP, safi);
+ }
+}
+
+ALIAS (show_bgp_instance_ipv4_safi_rsclient_summary,
+ show_bgp_ipv4_safi_rsclient_summary_cmd,
+ "show bgp ipv4 (unicast|multicast) rsclient summary",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Clients\n"
+ "Summary of all Route Server Clients\n")
+
#ifdef HAVE_IPV6
DEFUN (show_bgp_rsclient_summary,
show_bgp_rsclient_summary_cmd,
@@ -8198,6 +8333,42 @@ ALIAS (show_bgp_instance_rsclient_summary,
"Address family\n"
"Information about Route Server Clients\n"
"Summary of all Route Server Clients\n")
+
+DEFUN (show_bgp_instance_ipv6_safi_rsclient_summary,
+ show_bgp_instance_ipv6_safi_rsclient_summary_cmd,
+ "show bgp view WORD ipv6 (unicast|multicast) rsclient summary",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "View name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Clients\n"
+ "Summary of all Route Server Clients\n")
+{
+ safi_t safi;
+
+ if (argc == 2) {
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ return bgp_show_rsclient_summary_vty (vty, argv[0], AFI_IP6, safi);
+ } else {
+ safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ return bgp_show_rsclient_summary_vty (vty, NULL, AFI_IP6, safi);
+ }
+}
+
+ALIAS (show_bgp_instance_ipv6_safi_rsclient_summary,
+ show_bgp_ipv6_safi_rsclient_summary_cmd,
+ "show bgp ipv6 (unicast|multicast) rsclient summary",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Clients\n"
+ "Summary of all Route Server Clients\n")
+
#endif /* HAVE IPV6 */
/* Redistribute VTY commands. */
@@ -9627,38 +9798,50 @@ bgp_vty_init (void)
install_element (VIEW_NODE, &show_ip_bgp_summary_cmd);
install_element (VIEW_NODE, &show_ip_bgp_instance_summary_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_summary_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_summary_cmd);
install_element (VIEW_NODE, &show_ip_bgp_instance_ipv4_summary_cmd);
+ install_element (VIEW_NODE, &show_bgp_instance_ipv4_safi_summary_cmd);
install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_summary_cmd);
install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_summary_cmd);
#ifdef HAVE_IPV6
install_element (VIEW_NODE, &show_bgp_summary_cmd);
install_element (VIEW_NODE, &show_bgp_instance_summary_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_summary_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_summary_cmd);
install_element (VIEW_NODE, &show_bgp_instance_ipv6_summary_cmd);
+ install_element (VIEW_NODE, &show_bgp_instance_ipv6_safi_summary_cmd);
#endif /* HAVE_IPV6 */
install_element (RESTRICTED_NODE, &show_ip_bgp_summary_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_instance_summary_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_summary_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_summary_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_instance_ipv4_summary_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_instance_ipv4_safi_summary_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_all_summary_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_summary_cmd);
#ifdef HAVE_IPV6
install_element (RESTRICTED_NODE, &show_bgp_summary_cmd);
install_element (RESTRICTED_NODE, &show_bgp_instance_summary_cmd);
install_element (RESTRICTED_NODE, &show_bgp_ipv6_summary_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_summary_cmd);
install_element (RESTRICTED_NODE, &show_bgp_instance_ipv6_summary_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_instance_ipv6_safi_summary_cmd);
#endif /* HAVE_IPV6 */
install_element (ENABLE_NODE, &show_ip_bgp_summary_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_instance_summary_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_summary_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_summary_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_instance_ipv4_summary_cmd);
+ install_element (ENABLE_NODE, &show_bgp_instance_ipv4_safi_summary_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_summary_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_summary_cmd);
#ifdef HAVE_IPV6
install_element (ENABLE_NODE, &show_bgp_summary_cmd);
install_element (ENABLE_NODE, &show_bgp_instance_summary_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_summary_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_summary_cmd);
install_element (ENABLE_NODE, &show_bgp_instance_ipv6_summary_cmd);
+ install_element (ENABLE_NODE, &show_bgp_instance_ipv6_safi_summary_cmd);
#endif /* HAVE_IPV6 */
/* "show ip bgp neighbors" commands. */
@@ -9722,28 +9905,40 @@ bgp_vty_init (void)
install_element (VIEW_NODE, &show_ip_bgp_instance_rsclient_summary_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_rsclient_summary_cmd);
install_element (VIEW_NODE, &show_ip_bgp_instance_ipv4_rsclient_summary_cmd);
+ install_element (VIEW_NODE, &show_bgp_instance_ipv4_safi_rsclient_summary_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_summary_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_rsclient_summary_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_instance_rsclient_summary_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_rsclient_summary_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_instance_ipv4_rsclient_summary_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_instance_ipv4_safi_rsclient_summary_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_instance_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_instance_ipv4_rsclient_summary_cmd);
+ install_element (ENABLE_NODE, &show_bgp_instance_ipv4_safi_rsclient_summary_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_summary_cmd);
#ifdef HAVE_IPV6
install_element (VIEW_NODE, &show_bgp_rsclient_summary_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_rsclient_summary_cmd);
install_element (VIEW_NODE, &show_bgp_instance_rsclient_summary_cmd);
install_element (VIEW_NODE, &show_bgp_instance_ipv6_rsclient_summary_cmd);
+ install_element (VIEW_NODE, &show_bgp_instance_ipv6_safi_rsclient_summary_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_summary_cmd);
install_element (RESTRICTED_NODE, &show_bgp_rsclient_summary_cmd);
install_element (RESTRICTED_NODE, &show_bgp_ipv6_rsclient_summary_cmd);
install_element (RESTRICTED_NODE, &show_bgp_instance_rsclient_summary_cmd);
install_element (RESTRICTED_NODE, &show_bgp_instance_ipv6_rsclient_summary_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_instance_ipv6_safi_rsclient_summary_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_bgp_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_bgp_instance_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_bgp_instance_ipv6_rsclient_summary_cmd);
+ install_element (ENABLE_NODE, &show_bgp_instance_ipv6_safi_rsclient_summary_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_summary_cmd);
#endif /* HAVE_IPV6 */
/* "show ip bgp paths" commands. */
@@ -9784,6 +9979,10 @@ bgp_vty_init (void)
install_element (BGP_IPV6_NODE, &no_bgp_redistribute_ipv6_metric_rmap_cmd);
#endif /* HAVE_IPV6 */
+ /* ttl_security commands */
+ install_element (BGP_NODE, &neighbor_ttl_security_cmd);
+ install_element (BGP_NODE, &no_neighbor_ttl_security_cmd);
+
/* "show bgp memory" commands. */
install_element (VIEW_NODE, &show_bgp_memory_cmd);
install_element (RESTRICTED_NODE, &show_bgp_memory_cmd);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index d7af349a..76c519cb 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -232,12 +232,10 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
{
struct stream *s;
struct zapi_ipv4 api;
- unsigned long ifindex;
struct in_addr nexthop;
struct prefix_ipv4 p;
s = zclient->ibuf;
- ifindex = 0;
nexthop.s_addr = 0;
/* Type, flags, message. */
@@ -260,7 +258,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
{
api.ifindex_num = stream_getc (s);
- ifindex = stream_getl (s);
+ stream_getl (s); /* ifindex, unused */
}
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc (s);
@@ -310,12 +308,10 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
{
struct stream *s;
struct zapi_ipv6 api;
- unsigned long ifindex;
struct in6_addr nexthop;
struct prefix_ipv6 p;
s = zclient->ibuf;
- ifindex = 0;
memset (&nexthop, 0, sizeof (struct in6_addr));
/* Type, flags, message. */
@@ -338,7 +334,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
{
api.ifindex_num = stream_getc (s);
- ifindex = stream_getl (s);
+ stream_getl (s); /* ifindex, unused */
}
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc (s);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 0d462db9..5dc014be 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -695,7 +695,7 @@ peer_sort (struct peer *peer)
}
}
-static inline void
+static void
peer_free (struct peer *peer)
{
assert (peer->status == Deleted);
@@ -1379,6 +1379,7 @@ peer_group_get (struct bgp *bgp, const char *name)
group->conf->group = group;
group->conf->as = 0;
group->conf->ttl = 1;
+ group->conf->gtsm_hops = 0;
group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
@@ -1416,6 +1417,9 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
/* TTL */
peer->ttl = conf->ttl;
+ /* GTSM hops */
+ peer->gtsm_hops = conf->gtsm_hops;
+
/* Weight */
peer->weight = conf->weight;
@@ -2664,10 +2668,36 @@ peer_ebgp_multihop_set (struct peer *peer, int ttl)
{
struct peer_group *group;
struct listnode *node, *nnode;
+ struct peer *peer1;
if (peer_sort (peer) == BGP_PEER_IBGP)
return 0;
+ /* see comment in peer_ttl_security_hops_set() */
+ if (ttl != MAXTTL)
+ {
+ if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+ {
+ group = peer->group;
+ if (group->conf->gtsm_hops != 0)
+ return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
+
+ for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
+ {
+ if (peer_sort (peer1) == BGP_PEER_IBGP)
+ continue;
+
+ if (peer1->gtsm_hops != 0)
+ return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
+ }
+ }
+ else
+ {
+ if (peer->gtsm_hops != 0)
+ return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
+ }
+ }
+
peer->ttl = ttl;
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
@@ -2701,6 +2731,9 @@ peer_ebgp_multihop_unset (struct peer *peer)
if (peer_sort (peer) == BGP_PEER_IBGP)
return 0;
+ if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
+ return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
+
if (peer_group_active (peer))
peer->ttl = peer->group->conf->ttl;
else
@@ -4332,6 +4365,137 @@ peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
return 0;
}
+/* Set # of hops between us and BGP peer. */
+int
+peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
+{
+ struct peer_group *group;
+ struct listnode *node, *nnode;
+ struct peer *peer1;
+ int ret;
+
+ zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
+
+ if (peer_sort (peer) == BGP_PEER_IBGP)
+ return BGP_ERR_NO_IBGP_WITH_TTLHACK;
+
+ /* We cannot configure ttl-security hops when ebgp-multihop is already
+ set. For non peer-groups, the check is simple. For peer-groups, it's
+ slightly messy, because we need to check both the peer-group structure
+ and all peer-group members for any trace of ebgp-multihop configuration
+ before actually applying the ttl-security rules. Cisco really made a
+ mess of this configuration parameter, and OpenBGPD got it right.
+ */
+
+ if (peer->gtsm_hops == 0) {
+ if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+ {
+ group = peer->group;
+ if (group->conf->ttl != 1)
+ return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
+
+ for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
+ {
+ if (peer_sort (peer1) == BGP_PEER_IBGP)
+ continue;
+
+ if (peer1->ttl != 1)
+ return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
+ }
+ }
+ else
+ {
+ if (peer->ttl != 1)
+ return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
+ }
+ /* specify MAXTTL on outgoing packets */
+ ret = peer_ebgp_multihop_set (peer, MAXTTL);
+ if (ret != 0)
+ return ret;
+ }
+
+ peer->gtsm_hops = gtsm_hops;
+
+ if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+ {
+ if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
+ sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
+ }
+ else
+ {
+ group = peer->group;
+ for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
+ {
+ if (peer_sort (peer) == BGP_PEER_IBGP)
+ continue;
+
+ peer->gtsm_hops = group->conf->gtsm_hops;
+
+ /* Change setting of existing peer
+ * established then change value (may break connectivity)
+ * not established yet (teardown session and restart)
+ * no session then do nothing (will get handled by next connection)
+ */
+ if (peer->status == Established)
+ {
+ if (peer->fd >= 0 && peer->gtsm_hops != 0)
+ sockopt_minttl (peer->su.sa.sa_family, peer->fd,
+ MAXTTL + 1 - peer->gtsm_hops);
+ }
+ else if (peer->status < Established)
+ {
+ if (BGP_DEBUG (events, EVENTS))
+ zlog_debug ("%s Min-ttl changed", peer->host);
+ BGP_EVENT_ADD (peer, BGP_Stop);
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+peer_ttl_security_hops_unset (struct peer *peer)
+{
+ struct peer_group *group;
+ struct listnode *node, *nnode;
+ struct peer *opeer;
+
+ zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
+
+ if (peer_sort (peer) == BGP_PEER_IBGP)
+ return 0;
+
+ /* if a peer-group member, then reset to peer-group default rather than 0 */
+ if (peer_group_active (peer))
+ peer->gtsm_hops = peer->group->conf->gtsm_hops;
+ else
+ peer->gtsm_hops = 0;
+
+ opeer = peer;
+ if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+ {
+ if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
+ sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
+ }
+ else
+ {
+ group = peer->group;
+ for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
+ {
+ if (peer_sort (peer) == BGP_PEER_IBGP)
+ continue;
+
+ peer->gtsm_hops = 0;
+
+ if (peer->fd >= 0)
+ sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
+ }
+ }
+
+ return peer_ebgp_multihop_unset (opeer);
+}
+
int
peer_clear (struct peer *peer)
{
@@ -4557,12 +4721,10 @@ static void
bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
struct peer *peer, afi_t afi, safi_t safi)
{
- struct bgp_filter *filter;
struct peer *g_peer = NULL;
char buf[SU_ADDRSTRLEN];
char *addr;
- filter = &peer->filter[afi][safi];
addr = peer->host;
if (peer_group_active (peer))
g_peer = peer->group->conf;
@@ -4636,12 +4798,19 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
/* EBGP multihop. */
- if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
+ if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1 &&
+ !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
if (! peer_group_active (peer) ||
g_peer->ttl != peer->ttl)
vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
VTY_NEWLINE);
+ /* ttl-security hops */
+ if (peer_sort (peer) != BGP_PEER_IBGP && peer->gtsm_hops != 0)
+ if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
+ vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
+ peer->gtsm_hops, VTY_NEWLINE);
+
/* disable-connected-check. */
if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
if (! peer_group_active (peer) ||
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 91773e3c..892e7dec 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -303,6 +303,7 @@ struct peer
/* Peer information */
int fd; /* File descriptor */
int ttl; /* TTL of TCP connection to the peer. */
+ int gtsm_hops; /* minimum hopcount to peer */
char *desc; /* Description of the peer. */
unsigned short port; /* Destination port for peer */
char *host; /* Printable address of the peer. */
@@ -801,7 +802,9 @@ enum bgp_clear_type
#define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP -27
#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS -28
#define BGP_ERR_TCPSIG_FAILED -29
-#define BGP_ERR_MAX -30
+#define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK -30
+#define BGP_ERR_NO_IBGP_WITH_TTLHACK -31
+#define BGP_ERR_MAX -32
extern struct bgp_master *bm;
@@ -954,4 +957,7 @@ extern int peer_maximum_prefix_unset (struct peer *, afi_t, safi_t);
extern int peer_clear (struct peer *);
extern int peer_clear_soft (struct peer *, afi_t, safi_t, enum bgp_clear_type);
+extern int peer_ttl_security_hops_set (struct peer *, int);
+extern int peer_ttl_security_hops_unset (struct peer *);
+
#endif /* _QUAGGA_BGPD_H */