diff options
| author | Russ White <russ@riw.us> | 2023-08-22 12:15:24 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-22 12:15:24 -0400 |
| commit | 020d8488cf2c96136e783f0b2fe906bd864548c1 (patch) | |
| tree | 0454e3b38ac59579b8d227dfd1c5f0293c8374a8 | |
| parent | 30b0637172b064c2182eea16311bdd578fe65816 (diff) | |
| parent | f023a2e03f4a8924b3b5ef0136e291549a4b814c (diff) | |
Merge pull request #14214 from opensourcerouting/fix/handle_rfc7606_attr_len_remaining_data
bgpd: Treat-as-withdraw attribute if remaining data is not enough
| -rw-r--r-- | bgpd/bgp_attr.c | 50 |
1 files changed, 38 insertions, 12 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index e07af4ab03..45536d2c5c 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -3461,8 +3461,24 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr, /* Get attributes to the end of attribute length. */ while (BGP_INPUT_PNT(peer) < endp) { + startp = BGP_INPUT_PNT(peer); + + /* Fewer than three octets remain (or fewer than four + * octets, if the Attribute Flags field has the Extended + * Length bit set) when beginning to parse the attribute. + * That is, this case exists if there remains unconsumed + * data in the path attributes but yet insufficient data + * to encode a single minimum-sized path attribute. + * + * An error condition exists and the "treat-as-withdraw" + * approach MUST be used (unless some other, more severe + * error is encountered dictating a stronger approach), + * and the Total Attribute Length MUST be relied upon to + * enable the beginning of the NLRI field to be located. + */ + /* Check remaining length check.*/ - if (endp - BGP_INPUT_PNT(peer) < BGP_ATTR_MIN_LEN) { + if ((endp - startp) < BGP_ATTR_MIN_LEN) { /* XXX warning: long int format, int arg (arg 5) */ flog_warn( EC_BGP_ATTRIBUTE_TOO_SMALL, @@ -3471,17 +3487,22 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr, (unsigned long)(endp - stream_pnt(BGP_INPUT(peer)))); - bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); - ret = BGP_ATTR_PARSE_ERROR; + if (peer->sort != BGP_PEER_EBGP) { + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); + ret = BGP_ATTR_PARSE_ERROR; + } else { + ret = BGP_ATTR_PARSE_WITHDRAW; + } + goto done; } - /* Fetch attribute flag and type. */ - startp = BGP_INPUT_PNT(peer); - /* "The lower-order four bits of the Attribute Flags octet are - unused. They MUST be zero when sent and MUST be ignored when - received." */ + /* Fetch attribute flag and type. + * The lower-order four bits of the Attribute Flags octet are + * unused. They MUST be zero when sent and MUST be ignored when + * received. + */ flag = 0xF0 & stream_getc(BGP_INPUT(peer)); type = stream_getc(BGP_INPUT(peer)); @@ -3495,9 +3516,14 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr, (unsigned long)(endp - stream_pnt(BGP_INPUT(peer)))); - bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); - ret = BGP_ATTR_PARSE_ERROR; + if (peer->sort != BGP_PEER_EBGP) { + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); + ret = BGP_ATTR_PARSE_ERROR; + } else { + ret = BGP_ATTR_PARSE_WITHDRAW; + } + goto done; } |
