/* Well-known attribute check. */
int
-bgp_attr_check (struct peer *peer, struct attr *attr)
+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_AS_PATH)))
type = BGP_ATTR_AS_PATH;
- if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)))
- type = BGP_ATTR_NEXT_HOP;
+ /* 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)))
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 int bgp_attr_check (struct peer *, struct attr *, bgp_size_t);
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 *);
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 peer is configured specific
Address Family and Subsequent Address Family. */
if (peer->afc[AFI_IP][SAFI_UNICAST])
bgp_nlri_parse (peer, NULL, &withdraw);
if (update.length)
- {
- /* We check well-known attribute only for IPv4 unicast
- update. */
- ret = bgp_attr_check (peer, &attr);
- if (ret < 0)
- {
- bgp_attr_unintern_sub (&attr);
- return -1;
- }
-
- bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
- }
+ bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
if (mp_update.length
&& mp_update.afi == AFI_IP