diff options
author | Samanvitha B Bhargav <bsamanvitha@vmware.com> | 2023-08-11 12:32:16 +0200 |
---|---|---|
committer | Samanvitha B Bhargav <bsamanvitha@vmware.com> | 2023-08-12 13:10:05 +0200 |
commit | 32f91a88b6f5466b0449f63f4a40d975cdb152a8 (patch) | |
tree | 71d0b1265627845e17c2bba553f22838852cf528 /bgpd/bgp_attr.c | |
parent | bgpd: Fix update message error handling for total attribute length (diff) | |
download | frr-32f91a88b6f5466b0449f63f4a40d975cdb152a8.tar.xz frr-32f91a88b6f5466b0449f63f4a40d975cdb152a8.zip |
bgpd: Fix update message error handling for multiple same attributes
As per RFC7606 section 3g,
g. If the MP_REACH_NLRI attribute or the MP_UNREACH_NLRI [RFC4760]
attribute appears more than once in the UPDATE message, then a
NOTIFICATION message MUST be sent with the Error Subcode
"Malformed Attribute List". If any other attribute (whether
recognized or unrecognized) appears more than once in an UPDATE
message, then all the occurrences of the attribute other than the
first one SHALL be discarded and the UPDATE message will continue
to be processed.
However, notification is sent out currently for all the cases.
Fix:
For cases other than MP_REACH_NLRI & MP_UNREACH_NLRI, handling has been updated
to discard the occurrences other than the first one and proceed with further parsing.
Again, the handling is relaxed only for the EBGP case.
Also, since in case of error, the attribute is discarded &
stream pointer is being adjusted accordingly based on length,
the total attribute length sanity check case has been moved up in the function
to be checked before this case.
Signed-off-by: Samanvitha B Bhargav <bsamanvitha@vmware.com>
Diffstat (limited to 'bgpd/bgp_attr.c')
-rw-r--r-- | bgpd/bgp_attr.c | 60 |
1 files changed, 39 insertions, 21 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 2e6059d62..e07af4ab0 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -3507,27 +3507,6 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr, 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 (CHECK_BITMAP(seen, type)) { - flog_warn( - EC_BGP_ATTRIBUTE_REPEATED, - "%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); - ret = BGP_ATTR_PARSE_ERROR; - goto done; - } - - /* Set type to bitmap to check duplicate attribute. `type' is - unsigned char so it never overflow bitmap range. */ - - SET_BITMAP(seen, type); - /* Overflow check. */ attr_endp = BGP_INPUT_PNT(peer) + length; @@ -3599,6 +3578,45 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr, } } + /* If attribute appears more than once in the UPDATE message, + * for MP_REACH_NLRI & MP_UNREACH_NLRI attributes + * the Error Subcode is set to Malformed Attribute List. + * For all other attributes, all the occurances of the attribute + * other than the first occurence is discarded. (RFC7606 3g) + */ + + if (CHECK_BITMAP(seen, type)) { + /* Only relax error handling for eBGP peers */ + if (peer->sort != BGP_PEER_EBGP || + type == BGP_ATTR_MP_REACH_NLRI || type == BGP_ATTR_MP_UNREACH_NLRI) { + flog_warn( + EC_BGP_ATTRIBUTE_REPEATED, + "%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); + ret = BGP_ATTR_PARSE_ERROR; + goto done; + } else { + flog_warn( + EC_BGP_ATTRIBUTE_REPEATED, + "%s: error BGP attribute type %d appears twice in a message - discard attribute", + peer->host, type); + /* Adjust the stream getp to the end of the attribute, in case we + * haven't read all the attributes. + */ + stream_set_getp(BGP_INPUT(peer), + (startp - STREAM_DATA(BGP_INPUT(peer))) + (attr_endp - startp)); + continue; + } + } + + /* Set type to bitmap to check duplicate attribute. `type' is + unsigned char so it never overflow bitmap range. */ + + SET_BITMAP(seen, type); + struct bgp_attr_parser_args attr_args = { .peer = peer, .length = length, |