summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_attr.c')
-rw-r--r--bgpd/bgp_attr.c968
1 files changed, 529 insertions, 439 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index d43c104f..c5a710c8 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -38,32 +38,32 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_packet.h"
#include "bgpd/bgp_ecommunity.h"
-
+
/* Attribute strings for logging. */
-static const struct message attr_str [] =
-{
- { BGP_ATTR_ORIGIN, "ORIGIN" },
- { BGP_ATTR_AS_PATH, "AS_PATH" },
- { BGP_ATTR_NEXT_HOP, "NEXT_HOP" },
- { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
- { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" },
- { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
- { BGP_ATTR_AGGREGATOR, "AGGREGATOR" },
- { BGP_ATTR_COMMUNITIES, "COMMUNITY" },
+static const struct message attr_str [] =
+{
+ { BGP_ATTR_ORIGIN, "ORIGIN" },
+ { BGP_ATTR_AS_PATH, "AS_PATH" },
+ { BGP_ATTR_NEXT_HOP, "NEXT_HOP" },
+ { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
+ { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" },
+ { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
+ { BGP_ATTR_AGGREGATOR, "AGGREGATOR" },
+ { BGP_ATTR_COMMUNITIES, "COMMUNITY" },
{ BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" },
- { BGP_ATTR_CLUSTER_LIST, "CLUSTERLIST" },
+ { BGP_ATTR_CLUSTER_LIST, "CLUSTERLIST" },
{ BGP_ATTR_DPA, "DPA" },
{ BGP_ATTR_ADVERTISER, "ADVERTISER"} ,
{ BGP_ATTR_RCID_PATH, "RCID_PATH" },
{ BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
{ BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
{ BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" },
- { BGP_ATTR_AS4_PATH, "AS4_PATH" },
- { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
+ { BGP_ATTR_AS4_PATH, "AS4_PATH" },
+ { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
{ BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" },
};
static const int attr_str_max = sizeof(attr_str)/sizeof(attr_str[0]);
-
+
static struct hash *cluster_hash;
static void *
@@ -107,7 +107,7 @@ int
cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
{
int i;
-
+
for (i = 0; i < cluster->length / 4; i++)
if (cluster->list[i].s_addr == originator.s_addr)
return 1;
@@ -118,7 +118,6 @@ static unsigned int
cluster_hash_key_make (void *p)
{
const struct cluster_list *cluster = p;
-
return jhash(cluster->list, cluster->length, 0);
}
@@ -156,7 +155,7 @@ cluster_dup (struct cluster_list *cluster)
}
else
new->list = NULL;
-
+
return new;
}
#endif
@@ -199,7 +198,7 @@ cluster_finish (void)
hash_free (cluster_hash);
cluster_hash = NULL;
}
-
+
/* Unknown transit attribute. */
static struct hash *transit_hash;
@@ -250,8 +249,7 @@ transit_unintern (struct transit *transit)
static unsigned int
transit_hash_key_make (void *p)
{
- const struct transit * transit = p;
-
+ const struct transit * transit = p ;
return jhash(transit->val, transit->length, 0);
}
@@ -277,7 +275,7 @@ transit_finish (void)
hash_free (transit_hash);
transit_hash = NULL;
}
-
+
/* Attribute hash routines. */
static struct hash *attrhash;
@@ -337,18 +335,13 @@ attrhash_key_make (void *p)
{
const struct attr * attr = (struct attr *) p;
uint32_t key = 0;
-#define MIX(val) key = jhash_1word(val, key)
+#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;
- key += attr->med;
- key += attr->local_pref;
-
if (attr->extra)
{
MIX(attr->extra->aggregator_as);
@@ -356,12 +349,12 @@ attrhash_key_make (void *p)
MIX(attr->extra->weight);
MIX(attr->extra->mp_nexthop_global_in.s_addr);
}
-
+
if (attr->aspath)
MIX(aspath_key_make (attr->aspath));
if (attr->community)
MIX(community_hash_make (attr->community));
-
+
if (attr->extra)
{
if (attr->extra->ecommunity)
@@ -397,7 +390,7 @@ attrhash_cmp (const void *p1, const void *p2)
{
const struct attr_extra *ae1 = attr1->extra;
const struct attr_extra *ae2 = attr2->extra;
-
+
if (ae1 && ae2
&& ae1->aggregator_as == ae2->aggregator_as
&& ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
@@ -439,14 +432,14 @@ attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
{
struct attr *attr = backet->data;
- vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
- inet_ntoa (attr->nexthop), VTY_NEWLINE);
+ vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
+ safe_inet_ntoa (attr->nexthop), VTY_NEWLINE);
}
void
attr_show_all (struct vty *vty)
{
- hash_iterate (attrhash,
+ hash_iterate (attrhash,
(void (*)(struct hash_backet *, void *))
attr_show_all_iterator,
vty);
@@ -469,7 +462,38 @@ bgp_attr_hash_alloc (void *p)
return attr;
}
-/* Internet argument attribute. */
+/*------------------------------------------------------------------------------
+ * Internet argument attribute.
+ *
+ * 1. "internalise" and increase reference count for each of:
+ *
+ * attr->aspath
+ * attr->community
+ * attr->extra->ecommunity
+ * attr->extra->cluster
+ * attr->extra->transit
+ *
+ * Noting that the reference count for each of these is zero if they have not
+ * yet been internalised.
+ *
+ * Each of these pointers is updated to point at either a new entry in the
+ * relevant attribute store, or at the existing entry.
+ *
+ * 2. "internalise" the complete attribute object and increase its reference
+ * count.
+ *
+ * If the attribute collection is new, then this function returns a pointer
+ * to a brand new attribute object, complete with a copy of the attr->extra.
+ *
+ * If the attribute collection is not new, then this function returns a
+ * pointer to the stored attribute object.
+ *
+ * In any event, the pointer returned != pointer passed in.
+ *
+ * NB: the incoming attr reference count is ignored.
+ *
+ * Note that the original attr object remains with its own attr->extra object.
+ */
struct attr *
bgp_attr_intern (struct attr *attr)
{
@@ -493,14 +517,14 @@ bgp_attr_intern (struct attr *attr)
if (attr->extra)
{
struct attr_extra *attre = attr->extra;
-
+
if (attre->ecommunity)
{
if (! attre->ecommunity->refcnt)
attre->ecommunity = ecommunity_intern (attre->ecommunity);
else
attre->ecommunity->refcnt++;
-
+
}
if (attre->cluster)
{
@@ -517,21 +541,23 @@ bgp_attr_intern (struct attr *attr)
attre->transit->refcnt++;
}
}
-
+
find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
find->refcnt++;
-
+
return find;
}
-
-/* Make network statement's attribute. */
+/* Make network statement's attribute.
+ *
+ * All elements are interned, but not the attribute set itself.
+ */
struct attr *
bgp_attr_default_set (struct attr *attr, u_char origin)
{
memset (attr, 0, sizeof (struct attr));
bgp_attr_extra_get (attr);
-
+
attr->origin = origin;
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
attr->aspath = aspath_empty ();
@@ -553,15 +579,15 @@ 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_default_set(&attr, origin);
new = bgp_attr_intern (&attr);
bgp_attr_extra_free (&attr);
-
+
aspath_unintern (&new->aspath);
return new;
}
@@ -577,7 +603,7 @@ bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
memset (&attr, 0, sizeof (struct attr));
attre = bgp_attr_extra_get (&attr);
-
+
/* Origin attribute. */
attr.origin = origin;
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
@@ -613,154 +639,183 @@ bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
new = bgp_attr_intern (&attr);
bgp_attr_extra_free (&attr);
-
+
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)
+extern void
+bgp_attr_unintern_sub (struct attr *attr, bool free_extra)
{
/* 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. */
+ if (free_extra)
+ bgp_attr_extra_free (attr) ;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * Free bgp attribute and aspath.
+ *
+ * For all the elements of the given attributes:
+ *
+ * if the reference count != 0, decrement it
+ * if the reference count is now zero, remove from hash table and discard
+ * stored value.
+ *
+ * For the attribute object itself:
+ *
+ * decrement the reference count
+ * if the reference count is now zero, remove from hash table and discard
+ * stored value.
+ *
+ * So... do NOT do this to a set of attributes whose elements have not been
+ * interned !
+ *
+ * Can do this to an attribute object which has not been interned, because its
+ * reference count SHOULD be zero.
+ */
void
bgp_attr_unintern (struct attr **attr)
{
- struct attr *ret;
- struct attr tmp;
-
- /* Decrement attribute reference. */
- (*attr)->refcnt--;
-
+ struct attr tmp ;
+ struct attr_extra tmp_extra ;
+
+ /* Take copy of attributes so that can unintern sub-objects */
tmp = *(*attr);
-
+
if ((*attr)->extra)
{
- tmp.extra = bgp_attr_extra_new ();
+ tmp.extra = &tmp_extra ;
memcpy (tmp.extra, (*attr)->extra, sizeof (struct attr_extra));
}
-
- /* If reference becomes zero then free attribute object. */
- if ((*attr)->refcnt == 0)
- {
- ret = hash_release (attrhash, *attr);
- assert (ret != NULL);
- bgp_attr_extra_free (*attr);
- XFREE (MTYPE_ATTR, *attr);
- *attr = NULL;
- }
-
- bgp_attr_unintern_sub (&tmp);
-}
+ /* If reference becomes zero then free attribute object. */
+ if ((*attr)->refcnt != 0)
+ {
+ --(*attr)->refcnt ;
+ if ((*attr)->refcnt == 0)
+ {
+ struct attr *ret;
+ ret = hash_release (attrhash, *attr);
+ assert (ret != NULL);
+ bgp_attr_extra_free (*attr);
+ XFREE (MTYPE_ATTR, *attr); /* sets *attr = NULL */
+ } ;
+ } ;
+
+ /* Now the sub-objects */
+ bgp_attr_unintern_sub (&tmp, false) ; /* false => don't free extra */
+}
+
+/*------------------------------------------------------------------------------
+ * Release any element whose reference count is zero.
+ *
+ * This is used where attributes have been replaced, but not internalised, and
+ * which are no longer of interest -- typically where a route-map returns DENY.
+ */
void
bgp_attr_flush (struct attr *attr)
{
- if (attr->aspath && ! attr->aspath->refcnt)
+ if (attr->aspath && (attr->aspath->refcnt == 0))
aspath_free (attr->aspath);
- if (attr->community && ! attr->community->refcnt)
+ if (attr->community && (attr->community->refcnt == 0))
community_free (attr->community);
if (attr->extra)
{
struct attr_extra *attre = attr->extra;
-
- if (attre->ecommunity && ! attre->ecommunity->refcnt)
+ if (attre->ecommunity && (attre->ecommunity->refcnt == 0))
ecommunity_free (&attre->ecommunity);
- if (attre->cluster && ! attre->cluster->refcnt)
+ if (attre->cluster && (attre->cluster->refcnt == 0))
cluster_free (attre->cluster);
- if (attre->transit && ! attre->transit->refcnt)
+ if (attre->transit && (attre->transit->refcnt == 0))
transit_free (attre->transit);
}
}
-/* Implement draft-scudder-idr-optional-transitive behaviour and
+/* Implement draft-ietf-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)
+bgp_attr_malformed (struct peer *peer, u_char attr_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)
+ 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 (attr_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;
- }
-
- 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 */
+ /* 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:
+ break ;
+
+ /* 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.
+ */
+ default:
+ 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;
+ break ;
+ } ;
+ } ;
+
+ /* default to reset */
+ bgp_peer_down_error_with_data(peer, BGP_NOTIFY_UPDATE_ERR, subcode,
+ startp, length) ;
return BGP_ATTR_PARSE_ERROR;
-}
+} ;
/* Get origin attribute of the update message. */
static bgp_attr_parse_ret_t
-bgp_attr_origin (struct peer *peer, bgp_size_t length,
+bgp_attr_origin (struct peer *peer, bgp_size_t length,
struct attr *attr, u_char flag, u_char *startp)
{
bgp_size_t total;
@@ -775,11 +830,11 @@ bgp_attr_origin (struct peer *peer, bgp_size_t length,
attribute (type, length and value). */
if (flag != BGP_ATTR_FLAG_TRANS)
{
- zlog (peer->log, LOG_ERR,
+ zlog (peer->log, LOG_ERR,
"Origin attribute flag isn't transitive %d", flag);
return bgp_attr_malformed (peer, BGP_ATTR_ORIGIN, flag,
- BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
- startp, total);
+ BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+ startp, total);
}
/* If any recognized attribute has Attribute Length that conflicts
@@ -792,8 +847,8 @@ bgp_attr_origin (struct peer *peer, bgp_size_t length,
zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
length);
return bgp_attr_malformed (peer, BGP_ATTR_ORIGIN, flag,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- startp, total);
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ startp, total);
}
/* Fetch origin attribute. */
@@ -809,60 +864,87 @@ bgp_attr_origin (struct peer *peer, bgp_size_t length,
zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
attr->origin);
return bgp_attr_malformed (peer, BGP_ATTR_ORIGIN, flag,
- BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
- startp, total);
+ BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
+ startp, total);
}
/* Set oring attribute flag. */
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
- return 0;
-}
-
-/* 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)
+ return BGP_ATTR_PARSE_PROCEED ;
+}
+
+/*------------------------------------------------------------------------------
+ * Parse AS path information. This function is wrapper of aspath_parse.
+ *
+ * Parses AS_PATH or AS4_PATH.
+ *
+ * Returns: if valid: BGP_ATTR_PARSE_PROCEED
+ * and sets *p_asp = address of struct aspath in the hash of
+ * known aspaths, with reference count incremented.
+ *
+ * else: whatever bgp_attr_malformed() decides.
+ *
+ * NB: empty AS path (length == 0) is valid. The returned struct aspath will
+ * have segments == NULL and str == zero length string (unique).
+ */
+static bgp_attr_parse_ret_t
+bgp_attr_aspath (struct peer *peer, struct aspath** p_asp, bgp_size_t length,
+ struct attr *attr, u_char flag, u_char *startp,
+ u_char attr_type)
{
- bgp_size_t total;
+ u_char require ;
+ bool as4_path = (attr_type == BGP_ATTR_AS4_PATH) ;
- total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+ /* Check the attribute flags */
+ require = as4_path ? BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
+ : BGP_ATTR_FLAG_TRANS ;
- /* Flag check. */
- if (CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)
- || ! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
+ if ((flag & (BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS)) != require)
{
- zlog (peer->log, LOG_ERR,
- "As-Path attribute flag isn't transitive %d", flag);
- return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
- BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
- startp, total);
- }
+ bgp_size_t total;
- /*
- * peer with AS4 => will get 4Byte ASnums
- * otherwise, will get 16 Bit
- */
- attr->aspath = aspath_parse (peer->ibuf, length,
- CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
+ *p_asp = NULL ;
+
+ if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS))
+ zlog (peer->log, LOG_ERR, "%s attribute flag isn't transitive 0x%02X",
+ as4_path ? "AS4_PATH" : "AS_PATH", flag) ;
+
+ if ((flag & BGP_ATTR_FLAG_OPTIONAL) != (require & BGP_ATTR_FLAG_OPTIONAL))
+ zlog (peer->log, LOG_ERR, "%s attribute flag must %sbe optional 0x%02X",
+ as4_path ? "AS4_PATH" : "AS_PATH",
+ (flag & BGP_ATTR_FLAG_OPTIONAL) ? "not " : "", flag) ;
+
+ total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+
+ return bgp_attr_malformed (peer, attr_type, flag,
+ BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+ startp, total);
+ } ;
- /* In case of IBGP, length will be zero. */
- if (! attr->aspath)
+ /* Parse the AS_PATH/AS4_PATH body.
+ *
+ * For AS_PATH peer with AS4 => 4Byte ASN otherwise 2Byte ASN
+ * AS4_PATH 4Byte ASN
+ */
+ *p_asp = aspath_parse (peer->ibuf, length,
+ PEER_CAP_AS4_USE(peer) || as4_path, as4_path) ;
+ if (*p_asp == NULL)
{
- 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);
- }
+ zlog (peer->log, LOG_ERR, "Malformed %s from %s, length is %d",
+ as4_path ? "AS4_PATH" : "AS4_PATH", peer->host, length);
- /* Set aspath attribute flag. */
- attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
+ return bgp_attr_malformed (peer, attr_type, flag,
+ BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+ NULL, 0);
+ } ;
+
+ /* Success !
+ */
+ attr->flag |= ATTR_FLAG_BIT (attr_type) ;
return BGP_ATTR_PARSE_PROCEED;
-}
+} ;
static bgp_attr_parse_ret_t
bgp_attr_aspath_check (struct peer *peer, struct attr *attr, u_char flag)
@@ -876,30 +958,33 @@ bgp_attr_aspath_check (struct peer *peer, struct attr *attr, u_char flag)
*/
struct bgp *bgp = peer->bgp;
struct aspath *aspath;
+ bgp_peer_sort_t sort = peer_sort(peer) ;
bgp = peer->bgp;
-
+
/* Confederation sanity check. */
- if ((peer_sort (peer) == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
- (peer_sort (peer) == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
+ if ( ((sort == BGP_PEER_CONFED) && ! aspath_left_confed_check (attr->aspath))
+ || ((sort == BGP_PEER_EBGP) && aspath_confed_check (attr->aspath)) )
{
zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
+
return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
- BGP_NOTIFY_UPDATE_MAL_AS_PATH,
- NULL, 0);
+ BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+ NULL, 0);
}
/* First AS check for EBGP. */
if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
{
- if (peer_sort (peer) == BGP_PEER_EBGP
+ if (sort == BGP_PEER_EBGP
&& ! aspath_firstas_check (attr->aspath, peer->as))
{
zlog (peer->log, LOG_ERR,
"%s incorrect first AS (must be %u)", peer->host, peer->as);
+
return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
- BGP_NOTIFY_UPDATE_MAL_AS_PATH,
- NULL, 0);
+ BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+ NULL, 0);
}
}
@@ -916,51 +1001,9 @@ bgp_attr_aspath_check (struct peer *peer, struct attr *attr, u_char flag)
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_AS_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 bgp_attr_parse_ret_t
-bgp_attr_nexthop (struct peer *peer, bgp_size_t length,
+bgp_attr_nexthop (struct peer *peer, bgp_size_t length,
struct attr *attr, u_char flag, u_char *startp)
{
bgp_size_t total;
@@ -971,11 +1014,12 @@ bgp_attr_nexthop (struct peer *peer, bgp_size_t length,
if (CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)
|| ! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
{
- zlog (peer->log, LOG_ERR,
+ zlog (peer->log, LOG_ERR,
"Origin attribute flag isn't transitive %d", flag);
+
return bgp_attr_malformed (peer, BGP_ATTR_NEXT_HOP, flag,
- BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
- startp, total);
+ BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+ startp, total);
}
/* Check nexthop attribute length. */
@@ -985,8 +1029,8 @@ bgp_attr_nexthop (struct peer *peer, bgp_size_t length,
length);
return bgp_attr_malformed (peer, BGP_ATTR_NEXT_HOP, flag,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- startp, total);
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ startp, total);
}
attr->nexthop.s_addr = stream_get_ipv4 (peer->ibuf);
@@ -997,7 +1041,7 @@ bgp_attr_nexthop (struct peer *peer, bgp_size_t length,
/* MED atrribute. */
static bgp_attr_parse_ret_t
-bgp_attr_med (struct peer *peer, bgp_size_t length,
+bgp_attr_med (struct peer *peer, bgp_size_t length,
struct attr *attr, u_char flag, u_char *startp)
{
bgp_size_t total;
@@ -1007,12 +1051,12 @@ bgp_attr_med (struct peer *peer, bgp_size_t length,
/* Length check. */
if (length != 4)
{
- zlog (peer->log, LOG_ERR,
+ zlog (peer->log, LOG_ERR,
"MED attribute length isn't four [%d]", length);
return bgp_attr_malformed (peer, BGP_ATTR_MULTI_EXIT_DISC, flag,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- startp, total);
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ startp, total);
}
attr->med = stream_getl (peer->ibuf);
@@ -1024,7 +1068,7 @@ bgp_attr_med (struct peer *peer, bgp_size_t length,
/* Local preference attribute. */
static bgp_attr_parse_ret_t
-bgp_attr_local_pref (struct peer *peer, bgp_size_t length,
+bgp_attr_local_pref (struct peer *peer, bgp_size_t length,
struct attr *attr, u_char flag)
{
/* If it is contained in an UPDATE message that is received from an
@@ -1036,9 +1080,9 @@ bgp_attr_local_pref (struct peer *peer, bgp_size_t length,
return BGP_ATTR_PARSE_PROCEED;
}
- if (length == 4)
+ if (length == 4)
attr->local_pref = stream_getl (peer->ibuf);
- else
+ else
attr->local_pref = 0;
/* Set atomic aggregate flag. */
@@ -1049,7 +1093,7 @@ bgp_attr_local_pref (struct peer *peer, bgp_size_t length,
/* Atomic aggregate. */
static int
-bgp_attr_atomic (struct peer *peer, bgp_size_t length,
+bgp_attr_atomic (struct peer *peer, bgp_size_t length,
struct attr *attr, u_char flag)
{
if (length != 0)
@@ -1057,8 +1101,8 @@ bgp_attr_atomic (struct peer *peer, bgp_size_t length,
zlog (peer->log, LOG_ERR, "Bad atomic aggregate length %d", length);
return bgp_attr_malformed (peer, BGP_ATTR_ATOMIC_AGGREGATE, flag,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- NULL, 0);
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ NULL, 0);
}
/* Set atomic aggregate flag. */
@@ -1074,21 +1118,22 @@ bgp_attr_aggregator (struct peer *peer, bgp_size_t length,
{
int wantedlen = 6;
struct attr_extra *attre = bgp_attr_extra_get (attr);
-
+
/* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
- if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
+ if ( PEER_CAP_AS4_USE(peer) )
wantedlen = 8;
-
+
if (length != wantedlen)
{
- zlog (peer->log, LOG_ERR, "Aggregator length is not %d [%d]", wantedlen, length);
+ zlog (peer->log, LOG_ERR, "Aggregator length is not %d [%d]", wantedlen,
+ length);
return bgp_attr_malformed (peer, BGP_ATTR_AGGREGATOR, flag,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- NULL, 0);
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ NULL, 0);
}
-
- if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
+
+ if ( PEER_CAP_AS4_USE(peer) )
attre->aggregator_as = stream_getl (peer->ibuf);
else
attre->aggregator_as = stream_getw (peer->ibuf);
@@ -1103,7 +1148,7 @@ bgp_attr_aggregator (struct peer *peer, bgp_size_t length,
/* New Aggregator attribute */
static bgp_attr_parse_ret_t
bgp_attr_as4_aggregator (struct peer *peer, bgp_size_t length,
- struct attr *attr, u_char flag,
+ struct attr *attr, u_char flag,
as_t *as4_aggregator_as,
struct in_addr *as4_aggregator_addr)
{
@@ -1111,8 +1156,8 @@ bgp_attr_as4_aggregator (struct peer *peer, bgp_size_t length,
{
zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]", length);
return bgp_attr_malformed (peer, BGP_ATTR_AS4_AGGREGATOR, flag,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- NULL, 0);
+ 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);
@@ -1132,8 +1177,8 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr, u_char flag,
int ignore_as4_path = 0;
struct aspath *newpath;
struct attr_extra *attre = attr->extra;
-
- if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
+
+ if ( PEER_CAP_AS4_USE(peer) )
{
/* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
* if given.
@@ -1145,15 +1190,15 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr, u_char flag,
if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
zlog_debug ("[AS4] %s %s AS4_PATH",
peer->host, "AS4 capable peer, yet it sent");
-
+
if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
peer->host, "AS4 capable peer, yet it sent");
}
-
+
return BGP_ATTR_PARSE_PROCEED;
}
-
+
if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH))
&& !(attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))))
{
@@ -1164,12 +1209,13 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr, u_char flag,
* But... yeah, paranoia
* Take this as a "malformed attribute"
*/
- zlog (peer->log, LOG_ERR,
+ zlog (peer->log, LOG_ERR,
"%s BGP not AS4 capable peer sent AS4_PATH but"
" no AS_PATH, cant do anything here", peer->host);
+
return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
- BGP_NOTIFY_UPDATE_MAL_ATTR,
- NULL, 0);
+ BGP_NOTIFY_UPDATE_MAL_ATTR,
+ NULL, 0);
}
/* We have a asn16 peer. First, look for AS4_AGGREGATOR
@@ -1180,11 +1226,11 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr, u_char flag,
if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
{
assert (attre);
-
+
/* received both.
* if the as_number in aggregator is not AS_TRANS,
* then AS4_AGGREGATOR and AS4_PATH shall be ignored
- * and the Aggregator shall be taken as
+ * and the Aggregator shall be taken as
* info on the aggregating node, and the AS_PATH
* shall be taken as the AS_PATH
* otherwise
@@ -1197,7 +1243,7 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr, u_char flag,
{
/* ignore */
if ( BGP_DEBUG(as4, AS4))
- zlog_debug ("[AS4] %s BGP not AS4 capable peer"
+ zlog_debug ("[AS4] %s BGP not AS4 capable peer"
" send AGGREGATOR != AS_TRANS and"
" AS4_AGGREGATOR, so ignore"
" AS4_AGGREGATOR and AS4_PATH", peer->host);
@@ -1220,8 +1266,10 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr, u_char flag,
if ( BGP_DEBUG(as4, AS4))
zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
" AS4_AGGREGATOR but no AGGREGATOR, will take"
- " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
- (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
+ " it as if AGGREGATOR with AS_TRANS had been there",
+ peer->host);
+ attre = bgp_attr_extra_get (attr) ;
+ attre->aggregator_as = as4_aggregator;
/* sweep it under the carpet and simulate a "good" AGGREGATOR */
attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
}
@@ -1239,29 +1287,29 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr, u_char flag,
/* Community attribute. */
static bgp_attr_parse_ret_t
-bgp_attr_community (struct peer *peer, bgp_size_t length,
+bgp_attr_community (struct peer *peer, bgp_size_t length,
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 BGP_ATTR_PARSE_PROCEED;
}
-
+
attr->community =
community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
-
+
/* XXX: fix community_parse to use stream API and remove this */
stream_forward_getp (peer->ibuf, length);
if (!attr->community)
return bgp_attr_malformed (peer, BGP_ATTR_COMMUNITIES, flag,
- BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
- startp, total);
-
+ BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+ startp, total);
+
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
return BGP_ATTR_PARSE_PROCEED;
@@ -1269,7 +1317,7 @@ bgp_attr_community (struct peer *peer, bgp_size_t length,
/* Originator ID attribute. */
static bgp_attr_parse_ret_t
-bgp_attr_originator_id (struct peer *peer, bgp_size_t length,
+bgp_attr_originator_id (struct peer *peer, bgp_size_t length,
struct attr *attr, u_char flag)
{
if (length != 4)
@@ -1277,11 +1325,11 @@ bgp_attr_originator_id (struct peer *peer, bgp_size_t length,
zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
return bgp_attr_malformed (peer, BGP_ATTR_ORIGINATOR_ID, flag,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- NULL, 0);
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ NULL, 0);
}
- (bgp_attr_extra_get (attr))->originator_id.s_addr
+ (bgp_attr_extra_get (attr))->originator_id.s_addr
= stream_get_ipv4 (peer->ibuf);
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
@@ -1291,7 +1339,7 @@ bgp_attr_originator_id (struct peer *peer, bgp_size_t length,
/* Cluster list attribute. */
static bgp_attr_parse_ret_t
-bgp_attr_cluster_list (struct peer *peer, bgp_size_t length,
+bgp_attr_cluster_list (struct peer *peer, bgp_size_t length,
struct attr *attr, u_char flag)
{
/* Check length. */
@@ -1300,13 +1348,13 @@ bgp_attr_cluster_list (struct peer *peer, bgp_size_t length,
zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
return bgp_attr_malformed (peer, BGP_ATTR_CLUSTER_LIST, flag,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- NULL, 0);
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ NULL, 0);
}
- (bgp_attr_extra_get (attr))->cluster
+ (bgp_attr_extra_get (attr))->cluster
= cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
-
+
/* XXX: Fix cluster_parse to use stream API and then remove this */
stream_forward_getp (peer->ibuf, length);
@@ -1316,7 +1364,7 @@ bgp_attr_cluster_list (struct peer *peer, bgp_size_t length,
}
/* Multiprotocol reachability information parse. */
-int
+extern bgp_attr_parse_ret_t
bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr,
struct bgp_nlri *mp_update)
{
@@ -1327,35 +1375,35 @@ bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr,
int ret;
struct stream *s;
struct attr_extra *attre = bgp_attr_extra_get(attr);
-
+
/* Set end of packet. */
s = BGP_INPUT(peer);
start = stream_get_getp(s);
-
+
/* safe to read statically sized header? */
#define BGP_MP_REACH_MIN_SIZE 5
#define LEN_LEFT (length - (stream_get_getp(s) - start))
if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
{
- zlog_info ("%s: %s sent invalid length, %lu",
+ zlog_info ("%s: %s sent invalid length, %lu",
__func__, peer->host, (unsigned long)length);
return BGP_ATTR_PARSE_ERROR;
}
-
+
/* Load AFI, SAFI. */
afi = stream_getw (s);
safi = stream_getc (s);
/* Get nexthop length. */
attre->mp_nexthop_len = stream_getc (s);
-
+
if (LEN_LEFT < attre->mp_nexthop_len)
{
- zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
+ zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
__func__, peer->host, attre->mp_nexthop_len);
return BGP_ATTR_PARSE_ERROR;
}
-
+
/* Nexthop length check. */
switch (attre->mp_nexthop_len)
{
@@ -1388,7 +1436,9 @@ bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr,
char buf2[INET6_ADDRSTRLEN];
if (BGP_DEBUG (update, UPDATE_IN))
- zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host,
+ zlog_debug ("%s got two nexthop %s %s "
+ "but second one is not a link-local nexthop",
+ peer->host,
inet_ntop (AF_INET6, &attre->mp_nexthop_global,
buf1, INET6_ADDRSTRLEN),
inet_ntop (AF_INET6, &attre->mp_nexthop_local,
@@ -1399,7 +1449,7 @@ bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr,
break;
#endif /* HAVE_IPV6 */
default:
- zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
+ zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
__func__, peer->host, attre->mp_nexthop_len);
return BGP_ATTR_PARSE_ERROR;
}
@@ -1410,14 +1460,14 @@ bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr,
__func__, peer->host);
return BGP_ATTR_PARSE_ERROR;
}
-
+
{
- u_char val;
+ u_char val;
if ((val = stream_getc (s)))
zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
peer->host, val);
}
-
+
/* must have nrli_len, what is left of the attribute */
nlri_len = LEN_LEFT;
if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
@@ -1426,11 +1476,11 @@ bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr,
__func__, peer->host);
return BGP_ATTR_PARSE_ERROR;
}
-
+
if (safi != BGP_SAFI_VPNV4)
{
ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len);
- if (ret < 0)
+ if (ret < 0)
{
zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
__func__, peer->host);
@@ -1450,8 +1500,8 @@ bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr,
}
/* Multiprotocol unreachable parse */
-int
-bgp_mp_unreach_parse (struct peer *peer, bgp_size_t length,
+extern bgp_attr_parse_ret_t
+bgp_mp_unreach_parse (struct peer *peer, bgp_size_t length,
struct bgp_nlri *mp_withdraw)
{
struct stream *s;
@@ -1461,14 +1511,14 @@ bgp_mp_unreach_parse (struct peer *peer, bgp_size_t length,
int ret;
s = peer->ibuf;
-
+
#define BGP_MP_UNREACH_MIN_SIZE 3
if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
return BGP_ATTR_PARSE_ERROR;
-
+
afi = stream_getw (s);
safi = stream_getc (s);
-
+
withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
if (safi != BGP_SAFI_VPNV4)
@@ -1490,16 +1540,17 @@ bgp_mp_unreach_parse (struct peer *peer, bgp_size_t length,
/* Extended Community attribute. */
static bgp_attr_parse_ret_t
-bgp_attr_ext_communities (struct peer *peer, bgp_size_t length,
+bgp_attr_ext_communities (struct peer *peer, bgp_size_t length,
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 BGP_ATTR_PARSE_PROCEED;
}
@@ -1508,12 +1559,12 @@ bgp_attr_ext_communities (struct peer *peer, bgp_size_t length,
ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
/* XXX: fix ecommunity_parse to use stream API */
stream_forward_getp (peer->ibuf, length);
-
+
if (!attr->extra->ecommunity)
- return bgp_attr_malformed (peer, BGP_ATTR_EXT_COMMUNITIES,
- flag, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
- startp, total);
-
+ 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 BGP_ATTR_PARSE_PROCEED;
@@ -1531,9 +1582,9 @@ bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag,
if (BGP_DEBUG (normal, NORMAL))
zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
peer->host, type, length);
-
+
if (BGP_DEBUG (events, EVENTS))
- zlog (peer->log, LOG_DEBUG,
+ zlog (peer->log, LOG_DEBUG,
"Unknown attribute type %d length %d is received", type, length);
/* Forward read pointer of input stream. */
@@ -1549,8 +1600,8 @@ bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag,
if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
{
return bgp_attr_malformed (peer, type, flag,
- BGP_NOTIFY_UPDATE_UNREC_ATTR,
- startp, total);
+ BGP_NOTIFY_UPDATE_UNREC_ATTR,
+ startp, total);
}
/* Unrecognized non-transitive optional attributes must be quietly
@@ -1571,7 +1622,7 @@ bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag,
transit = attre->transit;
if (transit->val)
- transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
+ transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
transit->length + total);
else
transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
@@ -1582,8 +1633,25 @@ bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag,
return BGP_ATTR_PARSE_PROCEED;
}
-/* Read attribute of update packet. This function is called from
- bgp_update() in bgpd.c. */
+/*------------------------------------------------------------------------------
+ * Read attribute of update packet.
+ *
+ * This function is called from bgp_update() in bgpd.c.
+ *
+ * NB: expects the structures pointed to by:
+ *
+ * attr
+ * mp_update
+ * mp_withdraw
+ *
+ * to be zeroised on entry to this function.
+ *
+ * Any elements in attr or attr->extra will be internalised as they are set.
+ * (So their reference counts will *not* be zero.)
+ *
+ * However, the attr object itself is NOT internalised.
+ * (So its reference count will be zero.)
+ */
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)
@@ -1606,7 +1674,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)
{
@@ -1614,14 +1682,15 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
{
/* XXX warning: long int format, int arg (arg 5) */
- zlog (peer->log, LOG_WARNING,
+ zlog (peer->log, LOG_WARNING,
"%s error BGP attribute length %lu is smaller than min len",
peer->host,
(unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
- bgp_notify_send (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+ bgp_peer_down_error (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+ if (as4_path != NULL)
+ aspath_unintern (&as4_path);
return BGP_ATTR_PARSE_ERROR;
}
@@ -1634,42 +1703,44 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
&& ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
{
- zlog (peer->log, LOG_WARNING,
+ zlog (peer->log, LOG_WARNING,
"%s Extended length set, but just %lu bytes of attr header",
peer->host,
(unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
- bgp_notify_send (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+ bgp_peer_down_error (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+ if (as4_path != NULL)
+ aspath_unintern (&as4_path);
return BGP_ATTR_PARSE_ERROR;
}
- /* Check extended attribue length bit. */
+ /* Check extended attribute length bit. */
if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
length = stream_getw (BGP_INPUT (peer));
else
length = stream_getc (BGP_INPUT (peer));
-
- /* If any attribute appears more than once in the UPDATE
- message, then the Error Subcode is set to Malformed Attribute
- List. */
+ /* If any attribute appears more than once in the UPDATE
+ * message, then the Error Subcode is set to Malformed Attribute
+ * List.
+ */
if (CHECK_BITMAP (seen, type))
{
zlog (peer->log, LOG_WARNING,
"%s error BGP attribute type %d appears twice in a message",
peer->host, type);
- bgp_notify_send (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_MAL_ATTR);
+ bgp_peer_down_error (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_MAL_ATTR);
+ if (as4_path != NULL)
+ aspath_unintern (&as4_path);
return BGP_ATTR_PARSE_ERROR;
}
/* Set type to bitmap to check duplicate attribute. `type' is
- unsigned char so it never overflow bitmap range. */
-
+ * unsigned char so it never overflow bitmap range.
+ */
SET_BITMAP (seen, type);
/* Overflow check. */
@@ -1677,11 +1748,15 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
if (attr_endp > endp)
{
- zlog (peer->log, LOG_WARNING,
- "%s BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p", peer->host, type, length, size, attr_endp, endp);
- bgp_notify_send (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+ zlog (peer->log, LOG_WARNING,
+ "%s BGP type %d length %d is too large, "
+ "attribute total length is %d. attr_endp is %p. endp is %p",
+ peer->host, type, length, size, attr_endp, endp);
+
+ bgp_peer_down_error (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+ if (as4_path != NULL)
+ aspath_unintern (&as4_path);
return BGP_ATTR_PARSE_ERROR;
}
@@ -1692,12 +1767,14 @@ 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:
- ret = bgp_attr_aspath (peer, length, attr, flag, startp);
- break;
+ ret = bgp_attr_aspath (peer, &attr->aspath, length, attr, flag,
+ startp, BGP_ATTR_AS_PATH);
+ break;
case BGP_ATTR_AS4_PATH:
- ret = bgp_attr_as4_path (peer, length, attr, flag, startp, &as4_path);
+ ret = bgp_attr_aspath (peer, &as4_path, length, attr, flag,
+ startp, BGP_ATTR_AS4_PATH);
break;
- case BGP_ATTR_NEXT_HOP:
+ case BGP_ATTR_NEXT_HOP:
ret = bgp_attr_nexthop (peer, length, attr, flag, startp);
break;
case BGP_ATTR_MULTI_EXIT_DISC:
@@ -1714,7 +1791,7 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
break;
case BGP_ATTR_AS4_AGGREGATOR:
ret = bgp_attr_as4_aggregator (peer, length, attr, flag,
- &as4_aggregator,
+ &as4_aggregator,
&as4_aggregator_addr);
break;
case BGP_ATTR_COMMUNITIES:
@@ -1739,101 +1816,109 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
ret = bgp_attr_unknown (peer, attr, flag, type, length, startp);
break;
}
-
+
/* 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,
+ "%s: Attribute %s, parse error",
+ peer->host,
LOOKUP (attr_str, type));
- bgp_notify_send (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_MAL_ATTR);
- if (as4_path)
+
+ bgp_peer_down_error (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_MAL_ATTR);
+ if (as4_path != NULL)
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)
+
+ if (as4_path != NULL)
aspath_unintern (&as4_path);
return ret;
}
-
+
/* Check the fetched length. */
if (BGP_INPUT_PNT (peer) != attr_endp)
{
- zlog (peer->log, LOG_WARNING,
- "%s: BGP attribute %s, fetch error",
+ zlog (peer->log, LOG_WARNING,
+ "%s: BGP attribute %s, fetch error",
peer->host, LOOKUP (attr_str, type));
- bgp_notify_send (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- if (as4_path)
+
+ if (type == BGP_ATTR_AS_PATH)
+ {
+ zlog (peer->log, LOG_WARNING,
+ "%s: is %sAS4",
+ peer->host,
+ PEER_CAP_AS4_USE(peer) ? "" : "NOT ") ;
+ } ;
+
+ bgp_peer_down_error (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+ if (as4_path != NULL)
aspath_unintern (&as4_path);
- return BGP_ATTR_PARSE_ERROR;
+ return BGP_ATTR_PARSE_ERROR;
}
}
/* Check final read pointer is same as end pointer. */
if (BGP_INPUT_PNT (peer) != endp)
{
- zlog (peer->log, LOG_WARNING,
+ zlog (peer->log, LOG_WARNING,
"%s BGP attribute %s, length mismatch",
peer->host, LOOKUP (attr_str, type));
- bgp_notify_send (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- if (as4_path)
+
+ bgp_peer_down_error (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+ if (as4_path != NULL)
aspath_unintern (&as4_path);
return BGP_ATTR_PARSE_ERROR;
}
- /*
+ /*
* At this place we can see whether we got AS4_PATH and/or
* AS4_AGGREGATOR from a 16Bit peer and act accordingly.
* We can not do this before we've read all attributes because
* the as4 handling does not say whether AS4_PATH has to be sent
* after AS_PATH or not - and when AS4_AGGREGATOR will be send
* in relationship to AGGREGATOR.
+ *
* So, to be defensive, we are not relying on any order and read
* 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, flag, as4_path,
- as4_aggregator, &as4_aggregator_addr))
- {
- if (as4_path)
- aspath_unintern (&as4_path);
- return BGP_ATTR_PARSE_ERROR;
- }
+ ret = bgp_attr_munge_as4_attrs (peer, attr, flag, as4_path,
+ as4_aggregator, &as4_aggregator_addr) ;
/* 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)
- {
- 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
- */
- }
- /*
+ *
* The "rest" of the code does nothing with as4_aggregator.
* there is no memory attached specifically which is not part
* of the attr.
* so ignoring just means do nothing.
*/
- /*
- * Finally do the checks on the aspath we did not do yet
+ if (as4_path != NULL)
+ {
+ /* The flag that we got this is still there, but that does not
+ * do any trouble
+ */
+ aspath_unintern (&as4_path);
+ as4_path = NULL ;
+ } ;
+
+ if (ret != BGP_ATTR_PARSE_PROCEED)
+ return ret;
+
+ /* 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)))
@@ -1855,7 +1940,7 @@ int
bgp_attr_check (struct peer *peer, struct attr *attr)
{
u_char type = 0;
-
+
if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
type = BGP_ATTR_ORIGIN;
@@ -1871,18 +1956,18 @@ bgp_attr_check (struct peer *peer, struct attr *attr)
if (type)
{
- zlog (peer->log, LOG_WARNING,
+ zlog (peer->log, LOG_WARNING,
"%s Missing well-known attribute %d.",
peer->host, type);
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_MISS_ATTR,
- &type, 1);
+
+ bgp_peer_down_error_with_data (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_MISS_ATTR,
+ &type, 1);
return BGP_ATTR_PARSE_ERROR;
}
return BGP_ATTR_PARSE_PROCEED;
}
-
+
int stream_put_prefix (struct stream *, struct prefix *);
/* Make attribute packet. */
@@ -1897,7 +1982,8 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
struct aspath *aspath;
int send_as4_path = 0;
int send_as4_aggregator = 0;
- int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
+ int use32bit = PEER_CAP_AS4_USE(peer) ;
+ bgp_peer_sort_t sort ;
if (! bgp)
bgp = bgp_get_default ();
@@ -1914,11 +2000,13 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
/* AS path attribute. */
/* If remote-peer is EBGP */
- if (peer_sort (peer) == BGP_PEER_EBGP
+ sort = peer_sort(peer) ;
+
+ if (sort == BGP_PEER_EBGP
&& (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
|| attr->aspath->segments == NULL)
&& (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
- {
+ {
aspath = aspath_dup (attr->aspath);
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
@@ -1935,7 +2023,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
aspath = aspath_add_seq (aspath, peer->change_local_as);
}
}
- else if (peer_sort (peer) == BGP_PEER_CONFED)
+ else if (sort == BGP_PEER_CONFED)
{
/* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
aspath = aspath_dup (attr->aspath);
@@ -1958,13 +2046,13 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
aspath_sizep = stream_get_endp (s);
stream_putw (s, 0);
stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
-
- /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
+
+ /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
* in the path
*/
if (!use32bit && aspath_has_as4 (aspath))
send_as4_path = 1; /* we'll do this later, at the correct place */
-
+
/* Nexthop attribute. */
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP)
{
@@ -1992,8 +2080,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
}
/* Local preference. */
- if (peer_sort (peer) == BGP_PEER_IBGP ||
- peer_sort (peer) == BGP_PEER_CONFED)
+ if ((sort == BGP_PEER_IBGP) || (sort == BGP_PEER_CONFED))
{
stream_putc (s, BGP_ATTR_FLAG_TRANS);
stream_putc (s, BGP_ATTR_LOCAL_PREF);
@@ -2013,11 +2100,11 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
{
assert (attr->extra);
-
+
/* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
stream_putc (s, BGP_ATTR_AGGREGATOR);
-
+
if (use32bit)
{
/* AS4 capable peer */
@@ -2028,12 +2115,12 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
{
/* 2-byte AS peer */
stream_putc (s, 6);
-
+
/* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
if ( attr->extra->aggregator_as > 65535 )
{
stream_putw (s, BGP_AS_TRANS);
-
+
/* we have to send AS4_AGGREGATOR, too.
* we'll do that later in order to send attributes in ascending
* order.
@@ -2047,18 +2134,19 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
}
/* Community attribute. */
- if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
+ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
&& (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
{
if (attr->community->size * 4 > 255)
{
- stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
+ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
+ | BGP_ATTR_FLAG_EXTLEN);
stream_putc (s, BGP_ATTR_COMMUNITIES);
stream_putw (s, attr->community->size * 4);
}
else
{
- stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc (s, BGP_ATTR_COMMUNITIES);
stream_putc (s, attr->community->size * 4);
}
@@ -2066,9 +2154,8 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
}
/* Route Reflector. */
- if (peer_sort (peer) == BGP_PEER_IBGP
- && from
- && peer_sort (from) == BGP_PEER_IBGP)
+ if ( (sort == BGP_PEER_IBGP) && (from != NULL)
+ && (peer_sort (from) == BGP_PEER_IBGP) )
{
/* Originator ID. */
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
@@ -2077,13 +2164,13 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
stream_put_in_addr (s, &attr->extra->originator_id);
- else
+ else
stream_put_in_addr (s, &from->remote_id);
/* Cluster list. */
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
stream_putc (s, BGP_ATTR_CLUSTER_LIST);
-
+
if (attr->extra && attr->extra->cluster)
{
stream_putc (s, attr->extra->cluster->length + 4);
@@ -2092,7 +2179,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
stream_put_in_addr (s, &bgp->cluster_id);
else
stream_put_in_addr (s, &bgp->router_id);
- stream_put (s, attr->extra->cluster->list,
+ stream_put (s, attr->extra->cluster->list,
attr->extra->cluster->length);
}
else
@@ -2112,9 +2199,9 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
{
unsigned long sizep;
struct attr_extra *attre = attr->extra;
-
+
assert (attr->extra);
-
+
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
sizep = stream_get_endp (s);
@@ -2131,7 +2218,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
stream_put (s, &attre->mp_nexthop_global, 16);
stream_put (s, &attre->mp_nexthop_local, 16);
}
-
+
/* SNPA */
stream_putc (s, 0);
@@ -2197,25 +2284,25 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
}
/* Extended Communities attribute. */
- if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
+ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
&& (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
{
struct attr_extra *attre = attr->extra;
-
+
assert (attre);
-
- if (peer_sort (peer) == BGP_PEER_IBGP
- || peer_sort (peer) == BGP_PEER_CONFED)
+
+ if ((sort == BGP_PEER_IBGP) || (sort == BGP_PEER_CONFED))
{
if (attre->ecommunity->size * 8 > 255)
{
- stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
+ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
+ | BGP_ATTR_FLAG_EXTLEN);
stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
stream_putw (s, attre->ecommunity->size * 8);
}
else
{
- stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
stream_putc (s, attre->ecommunity->size * 8);
}
@@ -2243,13 +2330,14 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
{
if (ecom_tr_size * 8 > 255)
{
- stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
+ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
+ | BGP_ATTR_FLAG_EXTLEN);
stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
stream_putw (s, ecom_tr_size * 8);
}
else
{
- stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
stream_putc (s, ecom_tr_size * 8);
}
@@ -2279,12 +2367,13 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
* Hm, I wonder... confederation things *should* only be at
* the beginning of an aspath, right? Then we should use
* aspath_delete_confed_seq for this, because it is already
- * there! (JK)
+ * there! (JK)
* Folks, talk to me: what is reasonable here!?
*/
aspath = aspath_delete_confed_seq (aspath);
- stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
+ stream_putc (s, BGP_ATTR_FLAG_TRANS |BGP_ATTR_FLAG_OPTIONAL
+ | BGP_ATTR_FLAG_EXTLEN);
stream_putc (s, BGP_ATTR_AS4_PATH);
aspath_sizep = stream_get_endp (s);
stream_putw (s, 0);
@@ -2294,7 +2383,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
if (aspath != attr->aspath)
aspath_free (aspath);
- if ( send_as4_aggregator )
+ if ( send_as4_aggregator )
{
assert (attr->extra);
@@ -2308,7 +2397,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
stream_putl (s, attr->extra->aggregator_as);
stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
}
-
+
/* Unknown transit attribute. */
if (attr->extra && attr->extra->transit)
stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
@@ -2388,7 +2477,7 @@ bgp_attr_finish (void)
/* Make attribute packet. */
void
-bgp_dump_routes_attr (struct stream *s, struct attr *attr,
+bgp_dump_routes_attr (struct stream *s, struct attr *attr,
struct prefix *prefix)
{
unsigned long cp;
@@ -2409,12 +2498,12 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
stream_putc (s, attr->origin);
aspath = attr->aspath;
-
+
stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
stream_putc (s, BGP_ATTR_AS_PATH);
aspath_lenp = stream_get_endp (s);
stream_putw (s, 0);
-
+
stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
/* Nexthop attribute. */
@@ -2461,7 +2550,7 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
{
assert (attr->extra);
- stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc (s, BGP_ATTR_AGGREGATOR);
stream_putc (s, 8);
stream_putl (s, attr->extra->aggregator_as);
@@ -2473,7 +2562,8 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
{
if (attr->community->size * 4 > 255)
{
- stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
+ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
+ | BGP_ATTR_FLAG_EXTLEN);
stream_putc (s, BGP_ATTR_COMMUNITIES);
stream_putw (s, attr->community->size * 4);
}
@@ -2493,7 +2583,7 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
{
int sizep;
struct attr_extra *attre = attr->extra;
-
+
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
sizep = stream_get_endp (s);