summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2023-08-22 12:15:24 -0400
committerGitHub <noreply@github.com>2023-08-22 12:15:24 -0400
commit020d8488cf2c96136e783f0b2fe906bd864548c1 (patch)
tree0454e3b38ac59579b8d227dfd1c5f0293c8374a8
parent30b0637172b064c2182eea16311bdd578fe65816 (diff)
parentf023a2e03f4a8924b3b5ef0136e291549a4b814c (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.c50
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;
}