forked from Mirror/frr
bgpd: IPv6 session flapping with MP_REACH_NLRI and 0.0.0.0 in NEXT_HOP attribute
This is causing interop issues with vendors. According to the RFC, receiver should ignore the NEXT_HOP attribute with MP_REACH_NLRI present. Signed-off-by: nikos ntriantafillis@gmail.com
This commit is contained in:
parent
b1ad7351a5
commit
88f33d66ee
|
@ -1263,8 +1263,6 @@ static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args)
|
||||||
struct attr *const attr = args->attr;
|
struct attr *const attr = args->attr;
|
||||||
const bgp_size_t length = args->length;
|
const bgp_size_t length = args->length;
|
||||||
|
|
||||||
in_addr_t nexthop_h, nexthop_n;
|
|
||||||
|
|
||||||
/* Check nexthop attribute length. */
|
/* Check nexthop attribute length. */
|
||||||
if (length != 4) {
|
if (length != 4) {
|
||||||
flog_err(EC_BGP_ATTR_LEN,
|
flog_err(EC_BGP_ATTR_LEN,
|
||||||
|
@ -1274,30 +1272,7 @@ static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args)
|
||||||
args->total);
|
args->total);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
|
attr->nexthop.s_addr = stream_get_ipv4(peer->curr);
|
||||||
attribute must result in a NOTIFICATION message (this is implemented
|
|
||||||
below).
|
|
||||||
At the same time, semantically incorrect NEXT_HOP is more likely to
|
|
||||||
be just
|
|
||||||
logged locally (this is implemented somewhere else). The UPDATE
|
|
||||||
message
|
|
||||||
gets ignored in any of these cases. */
|
|
||||||
nexthop_n = stream_get_ipv4(peer->curr);
|
|
||||||
nexthop_h = ntohl(nexthop_n);
|
|
||||||
if ((IPV4_NET0(nexthop_h) || IPV4_NET127(nexthop_h)
|
|
||||||
|| IPV4_CLASS_DE(nexthop_h))
|
|
||||||
&& !BGP_DEBUG(
|
|
||||||
allow_martians,
|
|
||||||
ALLOW_MARTIANS)) /* loopbacks may be used in testing */
|
|
||||||
{
|
|
||||||
char buf[INET_ADDRSTRLEN];
|
|
||||||
inet_ntop(AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
|
|
||||||
flog_err(EC_BGP_ATTR_MARTIAN_NH, "Martian nexthop %s", buf);
|
|
||||||
return bgp_attr_malformed(
|
|
||||||
args, BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, args->total);
|
|
||||||
}
|
|
||||||
|
|
||||||
attr->nexthop.s_addr = nexthop_n;
|
|
||||||
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
|
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
|
||||||
|
|
||||||
return BGP_ATTR_PARSE_PROCEED;
|
return BGP_ATTR_PARSE_PROCEED;
|
||||||
|
@ -2681,6 +2656,40 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
|
||||||
return BGP_ATTR_PARSE_ERROR;
|
return BGP_ATTR_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
|
||||||
|
* then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
|
||||||
|
* This is implemented below and will result in a NOTIFICATION. If the
|
||||||
|
* NEXT_HOP attribute is semantically incorrect, the error SHOULD be
|
||||||
|
* logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
|
||||||
|
* message SHOULD NOT be sent. This is implemented elsewhere.
|
||||||
|
*
|
||||||
|
* RFC4760: An UPDATE message that carries no NLRI, other than the one
|
||||||
|
* encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
|
||||||
|
* attribute. If such a message contains the NEXT_HOP attribute, the BGP
|
||||||
|
* speaker that receives the message SHOULD ignore this attribute.
|
||||||
|
*/
|
||||||
|
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
|
||||||
|
&& !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI))) {
|
||||||
|
|
||||||
|
in_addr_t nexthop_h;
|
||||||
|
|
||||||
|
nexthop_h = ntohl(attr->nexthop.s_addr);
|
||||||
|
if ((IPV4_NET0(nexthop_h) || IPV4_NET127(nexthop_h)
|
||||||
|
|| IPV4_CLASS_DE(nexthop_h))
|
||||||
|
&& !BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) {
|
||||||
|
char buf[INET_ADDRSTRLEN];
|
||||||
|
|
||||||
|
inet_ntop(AF_INET, &attr->nexthop.s_addr, buf,
|
||||||
|
INET_ADDRSTRLEN);
|
||||||
|
flog_err(EC_BGP_ATTR_MARTIAN_NH, "Martian nexthop %s",
|
||||||
|
buf);
|
||||||
|
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
|
||||||
|
BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP);
|
||||||
|
return BGP_ATTR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Check all mandatory well-known attributes are present */
|
/* Check all mandatory well-known attributes are present */
|
||||||
if ((ret = bgp_attr_check(peer, attr)) < 0) {
|
if ((ret = bgp_attr_check(peer, attr)) < 0) {
|
||||||
if (as4_path)
|
if (as4_path)
|
||||||
|
|
Loading…
Reference in a new issue