]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_attr.c
bgpd: Fix confederation identifier unsigned display
[mirror_frr.git] / bgpd / bgp_attr.c
index 276a7054e37ae4007de403875b4f9ca32d191bad..e15ebf794a9a13737fc41e1d8a0a2a9e4240d7e0 100644 (file)
@@ -39,6 +39,7 @@
 #include "bgpd/bgp_aspath.h"
 #include "bgpd/bgp_community.h"
 #include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_errors.h"
 #include "bgpd/bgp_label.h"
 #include "bgpd/bgp_packet.h"
 #include "bgpd/bgp_ecommunity.h"
@@ -996,12 +997,14 @@ bgp_attr_flags_diagnose(struct bgp_attr_parser_args *args,
        for (i = 0; i <= 2; i++) /* O,T,P, but not E */
                if (CHECK_FLAG(desired_flags, attr_flag_str[i].key)
                    != CHECK_FLAG(real_flags, attr_flag_str[i].key)) {
-                       zlog_err("%s attribute must%s be flagged as \"%s\"",
-                                lookup_msg(attr_str, attr_code, NULL),
-                                CHECK_FLAG(desired_flags, attr_flag_str[i].key)
-                                        ? ""
-                                        : " not",
-                                attr_flag_str[i].str);
+                       flog_err(
+                               BGP_ERR_ATTR_FLAG,
+                               "%s attribute must%s be flagged as \"%s\"",
+                               lookup_msg(attr_str, attr_code, NULL),
+                               CHECK_FLAG(desired_flags, attr_flag_str[i].key)
+                                       ? ""
+                                       : " not",
+                               attr_flag_str[i].str);
                        seen = 1;
                }
        if (!seen) {
@@ -1059,7 +1062,8 @@ static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
         */
        if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL, flags)
            && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS, flags)) {
-               zlog_err(
+               flog_err(
+                       BGP_ERR_ATTR_FLAG,
                        "%s well-known attributes must have transitive flag set (%x)",
                        lookup_msg(attr_str, attr_code, NULL), flags);
                return 1;
@@ -1071,18 +1075,18 @@ static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
         */
        if (CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL)) {
                if (!CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)) {
-                       zlog_err(
-                               "%s well-known attribute "
-                               "must NOT have the partial flag set (%x)",
-                               lookup_msg(attr_str, attr_code, NULL), flags);
+                       flog_err(BGP_ERR_ATTR_FLAG,
+                                 "%s well-known attribute "
+                                 "must NOT have the partial flag set (%x)",
+                                 lookup_msg(attr_str, attr_code, NULL), flags);
                        return 1;
                }
                if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
                    && !CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)) {
-                       zlog_err(
-                               "%s optional + transitive attribute "
-                               "must NOT have the partial flag set (%x)",
-                               lookup_msg(attr_str, attr_code, NULL), flags);
+                       flog_err(BGP_ERR_ATTR_FLAG,
+                                 "%s optional + transitive attribute "
+                                 "must NOT have the partial flag set (%x)",
+                                 lookup_msg(attr_str, attr_code, NULL), flags);
                        return 1;
                }
        }
@@ -1114,7 +1118,8 @@ static bgp_attr_parse_ret_t bgp_attr_origin(struct bgp_attr_parser_args *args)
           field contains the erroneous attribute (type, length and
           value). */
        if (length != 1) {
-               zlog_err("Origin attribute length is not one %d", length);
+               flog_err(BGP_ERR_ATTR_LEN,
+                         "Origin attribute length is not one %d", length);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
        }
@@ -1127,7 +1132,8 @@ static bgp_attr_parse_ret_t bgp_attr_origin(struct bgp_attr_parser_args *args)
           contains the unrecognized attribute (type, length and value). */
        if ((attr->origin != BGP_ORIGIN_IGP) && (attr->origin != BGP_ORIGIN_EGP)
            && (attr->origin != BGP_ORIGIN_INCOMPLETE)) {
-               zlog_err("Origin attribute value is invalid %d", attr->origin);
+               flog_err(BGP_ERR_ATTR_ORIGIN,
+                         "Origin attribute value is invalid %d", attr->origin);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
                                          args->total);
        }
@@ -1155,8 +1161,9 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
 
        /* In case of IBGP, length will be zero. */
        if (!attr->aspath) {
-               zlog_err("Malformed AS path from %s, length is %d", peer->host,
-                        length);
+               flog_err(BGP_ERR_ATTR_MAL_AS_PATH,
+                         "Malformed AS path from %s, length is %d", peer->host,
+                         length);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
                                          0);
        }
@@ -1177,7 +1184,6 @@ static bgp_attr_parse_ret_t bgp_attr_aspath_check(struct peer *const peer,
         * not right.
         * So do the checks later, i.e. here
         */
-       struct bgp *bgp = peer->bgp;
        struct aspath *aspath;
 
        /* Confederation sanity check. */
@@ -1185,18 +1191,20 @@ static bgp_attr_parse_ret_t bgp_attr_aspath_check(struct peer *const peer,
             && !aspath_left_confed_check(attr->aspath))
            || (peer->sort == BGP_PEER_EBGP
                && aspath_confed_check(attr->aspath))) {
-               zlog_err("Malformed AS path from %s", peer->host);
+               flog_err(BGP_ERR_ATTR_MAL_AS_PATH, "Malformed AS path from %s",
+                         peer->host);
                bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
                                BGP_NOTIFY_UPDATE_MAL_AS_PATH);
                return BGP_ATTR_PARSE_ERROR;
        }
 
        /* First AS check for EBGP. */
-       if (bgp != NULL && bgp_flag_check(bgp, BGP_FLAG_ENFORCE_FIRST_AS)) {
+       if (CHECK_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS)) {
                if (peer->sort == BGP_PEER_EBGP
                    && !aspath_firstas_check(attr->aspath, peer->as)) {
-                       zlog_err("%s incorrect first AS (must be %u)",
-                                peer->host, peer->as);
+                       flog_err(BGP_ERR_ATTR_FIRST_AS,
+                                 "%s incorrect first AS (must be %u)",
+                                 peer->host, peer->as);
                        bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
                                        BGP_NOTIFY_UPDATE_MAL_AS_PATH);
                        return BGP_ATTR_PARSE_ERROR;
@@ -1228,8 +1236,9 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
 
        /* In case of IBGP, length will be zero. */
        if (!*as4_path) {
-               zlog_err("Malformed AS4 path from %s, length is %d", peer->host,
-                        length);
+               flog_err(BGP_ERR_ATTR_MAL_AS_PATH,
+                         "Malformed AS4 path from %s, length is %d",
+                         peer->host, length);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
                                          0);
        }
@@ -1251,7 +1260,8 @@ static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args)
 
        /* Check nexthop attribute length. */
        if (length != 4) {
-               zlog_err("Nexthop attribute length isn't four [%d]", length);
+               flog_err(BGP_ERR_ATTR_LEN,
+                         "Nexthop attribute length isn't four [%d]", length);
 
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
@@ -1275,7 +1285,7 @@ static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args)
        {
                char buf[INET_ADDRSTRLEN];
                inet_ntop(AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
-               zlog_err("Martian nexthop %s", buf);
+               flog_err(BGP_ERR_ATTR_MARTIAN_NH, "Martian nexthop %s", buf);
                return bgp_attr_malformed(
                        args, BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, args->total);
        }
@@ -1295,7 +1305,8 @@ static bgp_attr_parse_ret_t bgp_attr_med(struct bgp_attr_parser_args *args)
 
        /* Length check. */
        if (length != 4) {
-               zlog_err("MED attribute length isn't four [%d]", length);
+               flog_err(BGP_ERR_ATTR_LEN,
+                         "MED attribute length isn't four [%d]", length);
 
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
@@ -1318,7 +1329,8 @@ bgp_attr_local_pref(struct bgp_attr_parser_args *args)
 
        /* Length check. */
        if (length != 4) {
-               zlog_err("LOCAL_PREF attribute length isn't 4 [%u]", length);
+               flog_err(BGP_ERR_ATTR_LEN,
+                         "LOCAL_PREF attribute length isn't 4 [%u]", length);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
        }
@@ -1347,8 +1359,9 @@ static int bgp_attr_atomic(struct bgp_attr_parser_args *args)
 
        /* Length check. */
        if (length != 0) {
-               zlog_err("ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
-                        length);
+               flog_err(BGP_ERR_ATTR_LEN,
+                         "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
+                         length);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
        }
@@ -1373,8 +1386,9 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
                wantedlen = 8;
 
        if (length != wantedlen) {
-               zlog_err("AGGREGATOR attribute length isn't %u [%u]", wantedlen,
-                        length);
+               flog_err(BGP_ERR_ATTR_LEN,
+                         "AGGREGATOR attribute length isn't %u [%u]",
+                         wantedlen, length);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
        }
@@ -1402,7 +1416,8 @@ bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
        const bgp_size_t length = args->length;
 
        if (length != 8) {
-               zlog_err("New Aggregator length is not 8 [%d]", length);
+               flog_err(BGP_ERR_ATTR_LEN,
+                         "New Aggregator length is not 8 [%d]", length);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          0);
        }
@@ -1514,6 +1529,9 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
        if (!ignore_as4_path
            && (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))) {
                newpath = aspath_reconcile_as4(attr->aspath, as4_path);
+               if (!newpath)
+                       return BGP_ATTR_PARSE_ERROR;
+
                aspath_unintern(&attr->aspath);
                attr->aspath = aspath_intern(newpath);
        }
@@ -1558,7 +1576,8 @@ bgp_attr_originator_id(struct bgp_attr_parser_args *args)
 
        /* Length check. */
        if (length != 4) {
-               zlog_err("Bad originator ID length %d", length);
+               flog_err(BGP_ERR_ATTR_LEN, "Bad originator ID length %d",
+                         length);
 
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
@@ -1581,7 +1600,8 @@ bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
 
        /* Check length. */
        if (length % 4) {
-               zlog_err("Bad cluster list length %d", length);
+               flog_err(BGP_ERR_ATTR_LEN, "Bad cluster list length %d",
+                         length);
 
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
@@ -1670,7 +1690,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
                                 * - for consistency in rx processing
                                 *
                                 * The following comment is to signal GCC this intention
-                                * and supress the warning
+                                * and suppress the warning
                                 */
        /* FALLTHRU */
        case BGP_ATTR_NHLEN_IPV4:
@@ -1687,8 +1707,14 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
                        stream_getl(s); /* RD low */
                }
                stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
-               if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
+               if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
+                       if (!peer->nexthop.ifp) {
+                               zlog_warn("%s: interface not set appropriately to handle some attributes",
+                                         peer->host);
+                               return BGP_ATTR_PARSE_WITHDRAW;
+                       }
                        attr->nh_ifindex = peer->nexthop.ifp->ifindex;
+               }
                break;
        case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
        case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL:
@@ -1698,8 +1724,14 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
                        stream_getl(s); /* RD low */
                }
                stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
-               if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
+               if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
+                       if (!peer->nexthop.ifp) {
+                               zlog_warn("%s: interface not set appropriately to handle some attributes",
+                                         peer->host);
+                               return BGP_ATTR_PARSE_WITHDRAW;
+                       }
                        attr->nh_ifindex = peer->nexthop.ifp->ifindex;
+               }
                if (attr->mp_nexthop_len
                    == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
                        stream_getl(s); /* RD high */
@@ -1723,6 +1755,11 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
 
                        attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
                }
+               if (!peer->nexthop.ifp) {
+                       zlog_warn("%s: Interface not set appropriately to handle this some attributes",
+                                 peer->host);
+                       return BGP_ATTR_PARSE_WITHDRAW;
+               }
                attr->nh_lla_ifindex = peer->nexthop.ifp->ifindex;
                break;
        default:
@@ -1888,6 +1925,16 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
        /* Check if this is a Gateway MAC-IP advertisement */
        attr->default_gw = bgp_attr_default_gw(attr);
 
+       /* Handle scenario where router flag ecommunity is not
+        * set but default gw ext community is present.
+        * Use default gateway, set and propogate R-bit.
+        */
+       if (attr->default_gw)
+               attr->router_flag = 1;
+
+       /* Check EVPN Neighbor advertisement flags, R-bit */
+       bgp_attr_evpn_na_flag(attr, &attr->router_flag);
+
        /* Extract the Rmac, if any */
        bgp_attr_rmac(attr, &attr->rmac);
 
@@ -2040,10 +2087,10 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(int32_t type,
 
        if (type == BGP_PREFIX_SID_LABEL_INDEX) {
                if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
-                       zlog_err(
-                                "Prefix SID label index length is %d instead of %d",
-                                length,
-                                BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
+                       flog_err(
+                               BGP_ERR_ATTR_LEN,
+                               "Prefix SID label index length is %d instead of %d",
+                               length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
                        return bgp_attr_malformed(args,
                                                  BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                                  args->total);
@@ -2076,8 +2123,9 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(int32_t type,
        /* Placeholder code for the IPv6 SID type */
        else if (type == BGP_PREFIX_SID_IPV6) {
                if (length != BGP_PREFIX_SID_IPV6_LENGTH) {
-                       zlog_err("Prefix SID IPv6 length is %d instead of %d",
-                                length, BGP_PREFIX_SID_IPV6_LENGTH);
+                       flog_err(BGP_ERR_ATTR_LEN,
+                                 "Prefix SID IPv6 length is %d instead of %d",
+                                 length, BGP_PREFIX_SID_IPV6_LENGTH);
                        return bgp_attr_malformed(args,
                                                  BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                                  args->total);
@@ -2098,7 +2146,8 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(int32_t type,
                length -= 2;
 
                if (length % BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH) {
-                       zlog_err(
+                       flog_err(
+                               BGP_ERR_ATTR_LEN,
                                "Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
                                length, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH);
                        return bgp_attr_malformed(
@@ -2147,8 +2196,10 @@ bgp_attr_prefix_sid(int32_t tlength, struct bgp_attr_parser_args *args,
                tlength -= length + 3;
 
                if (tlength < 0) {
-                       zlog_err("Prefix SID internal length %d causes us to read beyond the total Prefix SID length",
-                                length);
+                       flog_err(
+                               BGP_ERR_ATTR_LEN,
+                               "Prefix SID internal length %d causes us to read beyond the total Prefix SID length",
+                               length);
                        return bgp_attr_malformed(args,
                                                  BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                                  args->total);
@@ -2173,21 +2224,24 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
         * can only support that.
         */
        if (length < 2) {
-               zlog_err("Bad PMSI tunnel attribute length %d", length);
+               flog_err(BGP_ERR_ATTR_LEN,
+                         "Bad PMSI tunnel attribute length %d", length);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
        }
        stream_getc(peer->curr); /* Flags */
        tnl_type = stream_getc(peer->curr);
        if (tnl_type > PMSI_TNLTYPE_MAX) {
-               zlog_err("Invalid PMSI tunnel attribute type %d", tnl_type);
+               flog_err(BGP_ERR_ATTR_PMSI_TYPE,
+                         "Invalid PMSI tunnel attribute type %d", tnl_type);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
                                          args->total);
        }
        if (tnl_type == PMSI_TNLTYPE_INGR_REPL) {
                if (length != 9) {
-                       zlog_err("Bad PMSI tunnel attribute length %d for IR",
-                                length);
+                       flog_err(BGP_ERR_ATTR_PMSI_LEN,
+                                 "Bad PMSI tunnel attribute length %d for IR",
+                                 length);
                        return bgp_attr_malformed(
                                args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                args->total);
@@ -2276,7 +2330,8 @@ static int bgp_attr_check(struct peer *peer, struct attr *attr)
           are present, it should.  Check for any other attribute being present
           instead.
         */
-       if (attr->flag == ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI))
+       if ((!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) &&
+            CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI))))
                return BGP_ATTR_PARSE_PROCEED;
 
        if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)))
@@ -2557,7 +2612,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
                        return ret;
                }
 
-               /* If hard error occured immediately return to the caller. */
+               /* If hard error occurred immediately return to the caller. */
                if (ret == BGP_ATTR_PARSE_ERROR) {
                        zlog_warn("%s: Attribute %s, parse error", peer->host,
                                  lookup_msg(attr_str, type, NULL));
@@ -2786,9 +2841,10 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
                break;
        default:
                if (safi != SAFI_FLOWSPEC)
-                       zlog_err(
-                                "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
-                                peer->host, afi, safi, attr->mp_nexthop_len);
+                       flog_err(
+                               BGP_ERR_ATTR_NH_SEND_LEN,
+                               "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
+                               peer->host, afi, safi, attr->mp_nexthop_len);
                break;
        }