summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_attr.c
diff options
context:
space:
mode:
authorSamanvitha B Bhargav <bsamanvitha@vmware.com>2023-08-11 12:32:16 +0200
committerSamanvitha B Bhargav <bsamanvitha@vmware.com>2023-08-12 13:10:05 +0200
commit32f91a88b6f5466b0449f63f4a40d975cdb152a8 (patch)
tree71d0b1265627845e17c2bba553f22838852cf528 /bgpd/bgp_attr.c
parentbgpd: Fix update message error handling for total attribute length (diff)
downloadfrr-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.c60
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,