]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Use treat-as-withdraw for tunnel encapsulation attribute
authorDonatas Abraitis <donatas@opensourcerouting.org>
Thu, 13 Jul 2023 19:32:03 +0000 (22:32 +0300)
committerMergify <37929162+mergify[bot]@users.noreply.github.com>
Tue, 29 Aug 2023 23:53:03 +0000 (23:53 +0000)
Before this path we used session reset method, which is discouraged by rfc7606.

Handle this as rfc requires.

Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
(cherry picked from commit bcb6b58d9530173df41d3a3cbc4c600ee0b4b186)

bgpd/bgp_attr.c

index 058fae23cbd2760f85e7bb920b014252666a0225..1c0803cfd8e40c3efad02ccc8e05ef5fe4904744 100644 (file)
@@ -1301,6 +1301,7 @@ bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
        case BGP_ATTR_LARGE_COMMUNITIES:
        case BGP_ATTR_ORIGINATOR_ID:
        case BGP_ATTR_CLUSTER_LIST:
+       case BGP_ATTR_ENCAP:
        case BGP_ATTR_OTC:
                return BGP_ATTR_PARSE_WITHDRAW;
        case BGP_ATTR_MP_REACH_NLRI:
@@ -2434,26 +2435,21 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
 }
 
 /* Parse Tunnel Encap attribute in an UPDATE */
-static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
-                         bgp_size_t length, /* IN: attr's length field */
-                         struct attr *attr, /* IN: caller already allocated */
-                         uint8_t flag,      /* IN: attr's flags field */
-                         uint8_t *startp)
+static int bgp_attr_encap(struct bgp_attr_parser_args *args)
 {
-       bgp_size_t total;
        uint16_t tunneltype = 0;
-
-       total = length + (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+       struct peer *const peer = args->peer;
+       struct attr *const attr = args->attr;
+       bgp_size_t length = args->length;
+       uint8_t type = args->type;
+       uint8_t flag = args->flags;
 
        if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
            || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) {
-               zlog_info(
-                       "Tunnel Encap attribute flag isn't optional and transitive %d",
-                       flag);
-               bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
-                                         BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
-                                         startp, total);
-               return -1;
+               zlog_err("Tunnel Encap attribute flag isn't optional and transitive %d",
+                        flag);
+               return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+                                         args->total);
        }
 
        if (BGP_ATTR_ENCAP == type) {
@@ -2461,12 +2457,11 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
                uint16_t tlv_length;
 
                if (length < 4) {
-                       zlog_info(
+                       zlog_err(
                                "Tunnel Encap attribute not long enough to contain outer T,L");
-                       bgp_notify_send_with_data(
-                               peer, BGP_NOTIFY_UPDATE_ERR,
-                               BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, startp, total);
-                       return -1;
+                       return bgp_attr_malformed(args,
+                                                 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+                                                 args->total);
                }
                tunneltype = stream_getw(BGP_INPUT(peer));
                tlv_length = stream_getw(BGP_INPUT(peer));
@@ -2496,13 +2491,11 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
                }
 
                if (sublength > length) {
-                       zlog_info(
-                               "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
-                               sublength, length);
-                       bgp_notify_send_with_data(
-                               peer, BGP_NOTIFY_UPDATE_ERR,
-                               BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, startp, total);
-                       return -1;
+                       zlog_err("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
+                                sublength, length);
+                       return bgp_attr_malformed(args,
+                                                 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+                                                 args->total);
                }
 
                /* alloc and copy sub-tlv */
@@ -2550,13 +2543,10 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
 
        if (length) {
                /* spurious leftover data */
-               zlog_info(
-                       "Tunnel Encap attribute length is bad: %d leftover octets",
-                       length);
-               bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
-                                         BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
-                                         startp, total);
-               return -1;
+               zlog_err("Tunnel Encap attribute length is bad: %d leftover octets",
+                        length);
+               return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+                                         args->total);
        }
 
        return 0;
@@ -3396,8 +3386,7 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
                case BGP_ATTR_VNC:
 #endif
                case BGP_ATTR_ENCAP:
-                       ret = bgp_attr_encap(type, peer, length, attr, flag,
-                                            startp);
+                       ret = bgp_attr_encap(&attr_args);
                        break;
                case BGP_ATTR_PREFIX_SID:
                        ret = bgp_attr_prefix_sid(&attr_args);