int ignore_as4_path = 0;
struct aspath *newpath;
struct attr_extra *attre = attr->extra;
-
+
+ if (!attr->aspath)
+ {
+ /* NULL aspath shouldn't be possible as bgp_attr_parse should have
+ * checked that all well-known, mandatory attributes were present.
+ *
+ * Can only be a problem with peer itself - hard error
+ */
+ return BGP_ATTR_PARSE_ERROR;
+ }
+
if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
{
/* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
/* need to reconcile NEW_AS_PATH and AS_PATH */
if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
{
- if (!attr->aspath)
- return BGP_ATTR_PARSE_PROCEED;
-
- newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
- aspath_unintern (&attr->aspath);
- attr->aspath = aspath_intern (newpath);
+ newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
+ aspath_unintern (&attr->aspath);
+ attr->aspath = aspath_intern (newpath);
}
return BGP_ATTR_PARSE_PROCEED;
}
return BGP_ATTR_PARSE_PROCEED;
}
+/* Well-known attribute check. */
+static int
+bgp_attr_check (struct peer *peer, struct attr *attr, bgp_size_t nlri_len)
+{
+ u_char type = 0;
+
+ if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
+ type = BGP_ATTR_ORIGIN;
+
+ if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
+ type = BGP_ATTR_AS_PATH;
+
+ /* As per RFC 2858, NEXT_HOP is needed only if the update contains NLRI
+ * other than in MP_REACH. In fact, if only MP_REACH_NLRI is present, the
+ * update should not contain NEXT_HOP but it should be ignored, if recvd.
+ */
+ if (nlri_len)
+ if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)))
+ type = BGP_ATTR_NEXT_HOP;
+
+ if (peer->sort == BGP_PEER_IBGP
+ && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
+ type = BGP_ATTR_LOCAL_PREF;
+
+ if (type)
+ {
+ zlog_warn ("%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);
+ return BGP_ATTR_PARSE_ERROR;
+ }
+ return BGP_ATTR_PARSE_PROCEED;
+}
+
/* Read attribute of update packet. This function is called from
bgp_update_receive() in bgp_packet.c. */
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)
+ struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw,
+ bgp_size_t nlri_len)
{
int ret;
u_char flag = 0;
return BGP_ATTR_PARSE_ERROR;
}
+ /* Check all mandatory well-known attributes are present */
+ {
+ bgp_attr_parse_ret_t ret;
+ if ((ret = bgp_attr_check (peer, attr, nlri_len)) < 0)
+ {
+ if (as4_path)
+ aspath_unintern (&as4_path);
+ return ret;
+ }
+ }
+
/*
* At this place we can see whether we got AS4_PATH and/or
* AS4_AGGREGATOR from a 16Bit peer and act accordingly.
return BGP_ATTR_PARSE_PROCEED;
}
-/* Well-known attribute check. */
-int
-bgp_attr_check (struct peer *peer, struct attr *attr, bgp_size_t nlri_len)
-{
- u_char type = 0;
-
- if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
- type = BGP_ATTR_ORIGIN;
-
- if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
- type = BGP_ATTR_AS_PATH;
-
- /* As per RFC 2858, NEXT_HOP is needed only if the update contains NLRI
- * other than in MP_REACH. In fact, if only MP_REACH_NLRI is present, the
- * update should not contain NEXT_HOP but it should be ignored, if recvd.
- */
- if (nlri_len)
- if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)))
- type = BGP_ATTR_NEXT_HOP;
-
- if (peer->sort == BGP_PEER_IBGP
- && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
- type = BGP_ATTR_LOCAL_PREF;
-
- if (type)
- {
- zlog_warn ("%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);
- return BGP_ATTR_PARSE_ERROR;
- }
- return BGP_ATTR_PARSE_PROCEED;
-}
-
size_t
bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
struct bpacket_attr_vec_arr *vecarr,
if (attribute_len)
{
attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
- &mp_update, &mp_withdraw);
+ &mp_update, &mp_withdraw, update.length);
if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
{
bgp_attr_unintern_sub (&attr);
peer->host, withdraw_len, num_pfx_wd, attribute_len,
update_len, num_pfx_adv);
- /*
- * Validate for well-known mandatory attributes. We only do this if
- * we intend to process the update further - i.e., the AFI/SAFI is
- * enabled.
- */
- if ((update.length && peer->afc[AFI_IP][SAFI_UNICAST]) ||
- (mp_update.length && peer->afc[mp_update.afi][mp_update.safi]))
- {
- ret = bgp_attr_check (peer, &attr, update.length);
- if (ret < 0)
- {
- bgp_attr_unintern_sub (&attr);
- return -1;
- }
- }
-
/* NLRI is processed only when the the corresponding address-family
* has been negotiated with the peer.
*/