]> 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:31 +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 d3a02a3df64151e99bb88d7945fb79a8b3d7222e..14e107c3acdf976b19e4e680a89472c237749c38 100644 (file)
@@ -1400,6 +1400,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:
@@ -2604,26 +2605,21 @@ ipv6_ext_community_ignore:
 }
 
 /* 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) {
@@ -2631,12 +2627,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));
@@ -2666,13 +2661,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 */
@@ -2720,13 +2713,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;
@@ -3637,8 +3627,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);