]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_attr.c
Merge pull request #3370 from pguibert6WIND/default_vrf_initialization
[mirror_frr.git] / bgpd / bgp_attr.c
index a993cc71c55ab042fd4ff5207a0fc0e551ab6aef..87ebb9c285f91eaf214fe3314d7048d2071019e3 100644 (file)
@@ -146,7 +146,7 @@ static unsigned int cluster_hash_key_make(void *p)
        return jhash(cluster->list, cluster->length, 0);
 }
 
-static int cluster_hash_cmp(const void *p1, const void *p2)
+static bool cluster_hash_cmp(const void *p1, const void *p2)
 {
        const struct cluster_list *cluster1 = p1;
        const struct cluster_list *cluster2 = p2;
@@ -260,11 +260,11 @@ void bgp_attr_flush_encap(struct attr *attr)
  *
  * This algorithm could be made faster if needed
  */
-static int encap_same(struct bgp_attr_encap_subtlv *h1,
-                     struct bgp_attr_encap_subtlv *h2)
+static int encap_same(const struct bgp_attr_encap_subtlv *h1,
+                     const struct bgp_attr_encap_subtlv *h2)
 {
-       struct bgp_attr_encap_subtlv *p;
-       struct bgp_attr_encap_subtlv *q;
+       const struct bgp_attr_encap_subtlv *p;
+       const struct bgp_attr_encap_subtlv *q;
 
        if (h1 == h2)
                return 1;
@@ -355,10 +355,10 @@ static unsigned int encap_hash_key_make(void *p)
        return jhash(encap->value, encap->length, 0);
 }
 
-static int encap_hash_cmp(const void *p1, const void *p2)
+static bool encap_hash_cmp(const void *p1, const void *p2)
 {
-       return encap_same((struct bgp_attr_encap_subtlv *)p1,
-                         (struct bgp_attr_encap_subtlv *)p2);
+       return encap_same((const struct bgp_attr_encap_subtlv *)p1,
+                         (const struct bgp_attr_encap_subtlv *)p2);
 }
 
 static void encap_init(void)
@@ -441,7 +441,7 @@ static unsigned int transit_hash_key_make(void *p)
        return jhash(transit->val, transit->length, 0);
 }
 
-static int transit_hash_cmp(const void *p1, const void *p2)
+static bool transit_hash_cmp(const void *p1, const void *p2)
 {
        const struct transit *transit1 = p1;
        const struct transit *transit2 = p2;
@@ -527,7 +527,7 @@ unsigned int attrhash_key_make(void *p)
        return key;
 }
 
-int attrhash_cmp(const void *p1, const void *p2)
+bool attrhash_cmp(const void *p1, const void *p2)
 {
        const struct attr *attr1 = p1;
        const struct attr *attr2 = p2;
@@ -565,10 +565,10 @@ int attrhash_cmp(const void *p1, const void *p2)
                    && overlay_index_same(attr1, attr2)
                    && attr1->nh_ifindex == attr2->nh_ifindex
                    && attr1->nh_lla_ifindex == attr2->nh_lla_ifindex)
-                       return 1;
+                       return true;
        }
 
-       return 0;
+       return false;
 }
 
 static void attrhash_init(void)
@@ -723,8 +723,10 @@ struct attr *bgp_attr_default_set(struct attr *attr, uint8_t origin)
 /* Create the attributes for an aggregate */
 struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin,
                                       struct aspath *aspath,
-                                      struct community *community, int as_set,
-                                      uint8_t atomic_aggregate)
+                                      struct community *community,
+                                      struct ecommunity *ecommunity,
+                                      struct lcommunity *lcommunity,
+                                      int as_set, uint8_t atomic_aggregate)
 {
        struct attr attr;
        struct attr *new;
@@ -760,6 +762,16 @@ struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin,
                attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
        }
 
+       if (ecommunity) {
+               attr.ecommunity = ecommunity;
+               attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
+       }
+
+       if (lcommunity) {
+               attr.lcommunity = lcommunity;
+               attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
+       }
+
        if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
                bgp_attr_add_gshut_community(&attr);
        }
@@ -837,7 +849,7 @@ void bgp_attr_undup(struct attr *new, struct attr *old)
                aspath_free(new->aspath);
 
        if (new->community != old->community)
-               community_free(new->community);
+               community_free(&new->community);
 
        if (new->ecommunity != old->ecommunity)
                ecommunity_free(&new->ecommunity);
@@ -875,11 +887,8 @@ void bgp_attr_flush(struct attr *attr)
                aspath_free(attr->aspath);
                attr->aspath = NULL;
        }
-       if (attr->community && !attr->community->refcnt) {
-               community_free(attr->community);
-               attr->community = NULL;
-       }
-
+       if (attr->community && !attr->community->refcnt)
+               community_free(&attr->community);
        if (attr->ecommunity && !attr->ecommunity->refcnt)
                ecommunity_free(&attr->ecommunity);
        if (attr->lcommunity && !attr->lcommunity->refcnt)
@@ -997,14 +1006,13 @@ 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)) {
-                       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);
+                       flog_err(EC_BGP_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) {
@@ -1063,7 +1071,7 @@ 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)) {
                flog_err(
-                       BGP_ERR_ATTR_FLAG,
+                       EC_BGP_ATTR_FLAG,
                        "%s well-known attributes must have transitive flag set (%x)",
                        lookup_msg(attr_str, attr_code, NULL), flags);
                return 1;
@@ -1075,18 +1083,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)) {
-                       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);
+                       flog_err(EC_BGP_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)) {
-                       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);
+                       flog_err(EC_BGP_ATTR_FLAG,
+                                "%s optional + transitive attribute "
+                                "must NOT have the partial flag set (%x)",
+                                lookup_msg(attr_str, attr_code, NULL), flags);
                        return 1;
                }
        }
@@ -1118,8 +1126,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) {
-               flog_err(BGP_ERR_ATTR_LEN,
-                         "Origin attribute length is not one %d", length);
+               flog_err(EC_BGP_ATTR_LEN,
+                        "Origin attribute length is not one %d", length);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
        }
@@ -1132,8 +1140,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)) {
-               flog_err(BGP_ERR_ATTR_ORIGIN,
-                         "Origin attribute value is invalid %d", attr->origin);
+               flog_err(EC_BGP_ATTR_ORIGIN,
+                        "Origin attribute value is invalid %d", attr->origin);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
                                          args->total);
        }
@@ -1161,9 +1169,9 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
 
        /* In case of IBGP, length will be zero. */
        if (!attr->aspath) {
-               flog_err(BGP_ERR_ATTR_MAL_AS_PATH,
-                         "Malformed AS path from %s, length is %d", peer->host,
-                         length);
+               flog_err(EC_BGP_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);
        }
@@ -1191,8 +1199,8 @@ 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))) {
-               flog_err(BGP_ERR_ATTR_MAL_AS_PATH, "Malformed AS path from %s",
-                         peer->host);
+               flog_err(EC_BGP_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;
@@ -1202,9 +1210,9 @@ static bgp_attr_parse_ret_t bgp_attr_aspath_check(struct peer *const peer,
        if (CHECK_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS)) {
                if (peer->sort == BGP_PEER_EBGP
                    && !aspath_firstas_check(attr->aspath, peer->as)) {
-                       flog_err(BGP_ERR_ATTR_FIRST_AS,
-                                 "%s incorrect first AS (must be %u)",
-                                 peer->host, peer->as);
+                       flog_err(EC_BGP_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;
@@ -1236,9 +1244,9 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
 
        /* In case of IBGP, length will be zero. */
        if (!*as4_path) {
-               flog_err(BGP_ERR_ATTR_MAL_AS_PATH,
-                         "Malformed AS4 path from %s, length is %d",
-                         peer->host, length);
+               flog_err(EC_BGP_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);
        }
@@ -1260,8 +1268,8 @@ static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args)
 
        /* Check nexthop attribute length. */
        if (length != 4) {
-               flog_err(BGP_ERR_ATTR_LEN,
-                         "Nexthop attribute length isn't four [%d]", length);
+               flog_err(EC_BGP_ATTR_LEN,
+                        "Nexthop attribute length isn't four [%d]", length);
 
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
@@ -1285,7 +1293,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);
-               flog_err(BGP_ERR_ATTR_MARTIAN_NH, "Martian nexthop %s", buf);
+               flog_err(EC_BGP_ATTR_MARTIAN_NH, "Martian nexthop %s", buf);
                return bgp_attr_malformed(
                        args, BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, args->total);
        }
@@ -1305,8 +1313,8 @@ static bgp_attr_parse_ret_t bgp_attr_med(struct bgp_attr_parser_args *args)
 
        /* Length check. */
        if (length != 4) {
-               flog_err(BGP_ERR_ATTR_LEN,
-                         "MED attribute length isn't four [%d]", length);
+               flog_err(EC_BGP_ATTR_LEN,
+                        "MED attribute length isn't four [%d]", length);
 
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
@@ -1329,8 +1337,8 @@ bgp_attr_local_pref(struct bgp_attr_parser_args *args)
 
        /* Length check. */
        if (length != 4) {
-               flog_err(BGP_ERR_ATTR_LEN,
-                         "LOCAL_PREF attribute length isn't 4 [%u]", length);
+               flog_err(EC_BGP_ATTR_LEN,
+                        "LOCAL_PREF attribute length isn't 4 [%u]", length);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
        }
@@ -1359,9 +1367,9 @@ static int bgp_attr_atomic(struct bgp_attr_parser_args *args)
 
        /* Length check. */
        if (length != 0) {
-               flog_err(BGP_ERR_ATTR_LEN,
-                         "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
-                         length);
+               flog_err(EC_BGP_ATTR_LEN,
+                        "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
+                        length);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
        }
@@ -1386,9 +1394,9 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
                wantedlen = 8;
 
        if (length != wantedlen) {
-               flog_err(BGP_ERR_ATTR_LEN,
-                         "AGGREGATOR attribute length isn't %u [%u]",
-                         wantedlen, length);
+               flog_err(EC_BGP_ATTR_LEN,
+                        "AGGREGATOR attribute length isn't %u [%u]", wantedlen,
+                        length);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
        }
@@ -1416,8 +1424,8 @@ bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
        const bgp_size_t length = args->length;
 
        if (length != 8) {
-               flog_err(BGP_ERR_ATTR_LEN,
-                         "New Aggregator length is not 8 [%d]", length);
+               flog_err(EC_BGP_ATTR_LEN, "New Aggregator length is not 8 [%d]",
+                        length);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          0);
        }
@@ -1576,8 +1584,8 @@ bgp_attr_originator_id(struct bgp_attr_parser_args *args)
 
        /* Length check. */
        if (length != 4) {
-               flog_err(BGP_ERR_ATTR_LEN, "Bad originator ID length %d",
-                         length);
+               flog_err(EC_BGP_ATTR_LEN, "Bad originator ID length %d",
+                        length);
 
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
@@ -1600,8 +1608,7 @@ bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
 
        /* Check length. */
        if (length % 4) {
-               flog_err(BGP_ERR_ATTR_LEN, "Bad cluster list length %d",
-                         length);
+               flog_err(EC_BGP_ATTR_LEN, "Bad cluster list length %d", length);
 
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                          args->total);
@@ -1690,7 +1697,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:
@@ -1707,8 +1714,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:
@@ -1718,8 +1731,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 */
@@ -1743,6 +1762,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:
@@ -1760,9 +1784,10 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
        {
                uint8_t val;
                if ((val = stream_getc(s)))
-                       flog_warn(BGP_WARN_DEFUNCT_SNPA_LEN,
-                                 "%s sent non-zero value, %u, for defunct SNPA-length field",
-                                 peer->host, val);
+                       flog_warn(
+                               EC_BGP_DEFUNCT_SNPA_LEN,
+                               "%s sent non-zero value, %u, for defunct SNPA-length field",
+                               peer->host, val);
        }
 
        /* must have nrli_len, what is left of the attribute */
@@ -2071,7 +2096,7 @@ 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) {
                        flog_err(
-                               BGP_ERR_ATTR_LEN,
+                               EC_BGP_ATTR_LEN,
                                "Prefix SID label index length is %d instead of %d",
                                length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
                        return bgp_attr_malformed(args,
@@ -2106,9 +2131,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) {
-                       flog_err(BGP_ERR_ATTR_LEN,
-                                 "Prefix SID IPv6 length is %d instead of %d",
-                                 length, BGP_PREFIX_SID_IPV6_LENGTH);
+                       flog_err(EC_BGP_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);
@@ -2130,7 +2155,7 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(int32_t type,
 
                if (length % BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH) {
                        flog_err(
-                               BGP_ERR_ATTR_LEN,
+                               EC_BGP_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(
@@ -2180,7 +2205,7 @@ bgp_attr_prefix_sid(int32_t tlength, struct bgp_attr_parser_args *args,
 
                if (tlength < 0) {
                        flog_err(
-                               BGP_ERR_ATTR_LEN,
+                               EC_BGP_ATTR_LEN,
                                "Prefix SID internal length %d causes us to read beyond the total Prefix SID length",
                                length);
                        return bgp_attr_malformed(args,
@@ -2207,24 +2232,24 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
         * can only support that.
         */
        if (length < 2) {
-               flog_err(BGP_ERR_ATTR_LEN,
-                         "Bad PMSI tunnel attribute length %d", length);
+               flog_err(EC_BGP_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) {
-               flog_err(BGP_ERR_ATTR_PMSI_TYPE,
-                         "Invalid PMSI tunnel attribute type %d", tnl_type);
+               flog_err(EC_BGP_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) {
-                       flog_err(BGP_ERR_ATTR_PMSI_LEN,
-                                 "Bad PMSI tunnel attribute length %d for IR",
-                                 length);
+                       flog_err(EC_BGP_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);
@@ -2336,7 +2361,7 @@ static int bgp_attr_check(struct peer *peer, struct attr *attr)
                type = BGP_ATTR_LOCAL_PREF;
 
        if (type) {
-               flog_warn(BGP_WARN_MISSING_ATTRIBUTE,
+               flog_warn(EC_BGP_MISSING_ATTRIBUTE,
                          "%s Missing well-known attribute %s.", peer->host,
                          lookup_msg(attr_str, type, NULL));
                bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
@@ -2353,7 +2378,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
                                    bgp_size_t size, struct bgp_nlri *mp_update,
                                    struct bgp_nlri *mp_withdraw)
 {
-       int ret;
+       bgp_attr_parse_ret_t ret;
        uint8_t flag = 0;
        uint8_t type = 0;
        bgp_size_t length;
@@ -2378,11 +2403,12 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
                /* Check remaining length check.*/
                if (endp - BGP_INPUT_PNT(peer) < BGP_ATTR_MIN_LEN) {
                        /* XXX warning: long int format, int arg (arg 5) */
-                       flog_warn(BGP_WARN_ATTRIBUTE_TOO_SMALL,
-                                 "%s: error BGP attribute length %lu is smaller than min len",
-                                 peer->host,
-                                 (unsigned long)(endp
-                                                 - stream_pnt(BGP_INPUT(peer))));
+                       flog_warn(
+                               EC_BGP_ATTRIBUTE_TOO_SMALL,
+                               "%s: error BGP attribute length %lu is smaller than min len",
+                               peer->host,
+                               (unsigned long)(endp
+                                               - stream_pnt(BGP_INPUT(peer))));
 
                        bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
                                        BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
@@ -2400,11 +2426,12 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
                /* Check whether Extended-Length applies and is in bounds */
                if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN)
                    && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) {
-                       flog_warn(BGP_WARN_EXT_ATTRIBUTE_TOO_SMALL,
-                                 "%s: Extended length set, but just %lu bytes of attr header",
-                                 peer->host,
-                                 (unsigned long)(endp
-                                                 - stream_pnt(BGP_INPUT(peer))));
+                       flog_warn(
+                               EC_BGP_EXT_ATTRIBUTE_TOO_SMALL,
+                               "%s: Extended length set, but just %lu bytes of attr header",
+                               peer->host,
+                               (unsigned long)(endp
+                                               - stream_pnt(BGP_INPUT(peer))));
 
                        bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
                                        BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
@@ -2422,9 +2449,10 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
                   List. */
 
                if (CHECK_BITMAP(seen, type)) {
-                       flog_warn(BGP_WARN_ATTRIBUTE_REPEATED,
-                                 "%s: error BGP attribute type %d appears twice in a message",
-                                 peer->host, type);
+                       flog_warn(
+                               EC_BGP_ATTRIBUTE_REPEATED,
+                               "%s: error BGP attribute type %d appears twice in a message",
+                               peer->host, type);
 
                        bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
                                        BGP_NOTIFY_UPDATE_MAL_ATTR);
@@ -2440,10 +2468,11 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
                attr_endp = BGP_INPUT_PNT(peer) + length;
 
                if (attr_endp > endp) {
-                       flog_warn(BGP_WARN_ATTRIBUTE_TOO_LARGE,
-                                 "%s: BGP type %d length %d is too large, attribute total length is %d.  attr_endp is %p.  endp is %p",
-                                 peer->host, type, length, size, attr_endp,
-                                 endp);
+                       flog_warn(
+                               EC_BGP_ATTRIBUTE_TOO_LARGE,
+                               "%s: BGP type %d length %d is too large, attribute total length is %d.  attr_endp is %p.  endp is %p",
+                               peer->host, type, length, size, attr_endp,
+                               endp);
                        /*
                         * RFC 4271 6.3
                         * If any recognized attribute has an Attribute
@@ -2504,7 +2533,6 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
                   Attribute Flags Error.  The Data field contains the erroneous
                   attribute (type, length and value). */
                if (bgp_attr_flag_invalid(&attr_args)) {
-                       bgp_attr_parse_ret_t ret;
                        ret = bgp_attr_malformed(
                                &attr_args, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
                                attr_args.total);
@@ -2596,9 +2624,9 @@ 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) {
-                       flog_warn(BGP_WARN_ATTRIBUTE_PARSE_ERROR,
+                       flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR,
                                  "%s: Attribute %s, parse error", peer->host,
                                  lookup_msg(attr_str, type, NULL));
                        if (as4_path)
@@ -2607,7 +2635,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
                }
                if (ret == BGP_ATTR_PARSE_WITHDRAW) {
 
-                       flog_warn(BGP_WARN_ATTRIBUTE_PARSE_WITHDRAW,
+                       flog_warn(
+                               EC_BGP_ATTRIBUTE_PARSE_WITHDRAW,
                                "%s: Attribute %s, parse error - treating as withdrawal",
                                peer->host, lookup_msg(attr_str, type, NULL));
                        if (as4_path)
@@ -2617,7 +2646,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
 
                /* Check the fetched length. */
                if (BGP_INPUT_PNT(peer) != attr_endp) {
-                       flog_warn(BGP_WARN_ATTRIBUTE_FETCH_ERROR,
+                       flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR,
                                  "%s: BGP attribute %s, fetch error",
                                  peer->host, lookup_msg(attr_str, type, NULL));
                        bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
@@ -2630,7 +2659,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
 
        /* Check final read pointer is same as end pointer. */
        if (BGP_INPUT_PNT(peer) != endp) {
-               flog_warn(BGP_WARN_ATTRIBUTES_MISMATCH,
+               flog_warn(EC_BGP_ATTRIBUTES_MISMATCH,
                          "%s: BGP attribute %s, length mismatch", peer->host,
                          lookup_msg(attr_str, type, NULL));
                bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
@@ -2641,13 +2670,10 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
        }
 
        /* Check all mandatory well-known attributes are present */
-       {
-               bgp_attr_parse_ret_t ret;
-               if ((ret = bgp_attr_check(peer, attr)) < 0) {
-                       if (as4_path)
-                               aspath_unintern(&as4_path);
-                       return ret;
-               }
+       if ((ret = bgp_attr_check(peer, attr)) < 0) {
+               if (as4_path)
+                       aspath_unintern(&as4_path);
+               return ret;
        }
 
        /*
@@ -2829,7 +2855,7 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
        default:
                if (safi != SAFI_FLOWSPEC)
                        flog_err(
-                               BGP_ERR_ATTR_NH_SEND_LEN,
+                               EC_BGP_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;
@@ -3469,8 +3495,8 @@ void bgp_packet_mpunreach_prefix(struct stream *s, struct prefix *p, afi_t afi,
                num_labels = 1;
        }
 
-       return bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, num_labels,
-                                       addpath_encode, addpath_tx_id, attr);
+       bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, num_labels,
+                                addpath_encode, addpath_tx_id, attr);
 }
 
 void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt)