]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_attr.c
Merge pull request #11177 from opensourcerouting/fix/memset_memcpy
[mirror_frr.git] / bgpd / bgp_attr.c
index 21f92c353eeca571d63e154bff86ea60ab820498..6c10469da8267ca05f311a3e5d2c27ae68be19c6 100644 (file)
@@ -669,9 +669,8 @@ unsigned int attrhash_key_make(const void *p)
 
        if (attr->aspath)
                MIX(aspath_key_make(attr->aspath));
-       if (attr->community)
-               MIX(community_hash_make(attr->community));
-
+       if (bgp_attr_get_community(attr))
+               MIX(community_hash_make(bgp_attr_get_community(attr)));
        if (bgp_attr_get_lcommunity(attr))
                MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr)));
        if (bgp_attr_get_ecommunity(attr))
@@ -713,7 +712,9 @@ bool attrhash_cmp(const void *p1, const void *p2)
        if (attr1->flag == attr2->flag && attr1->origin == attr2->origin
            && attr1->nexthop.s_addr == attr2->nexthop.s_addr
            && attr1->aspath == attr2->aspath
-           && attr1->community == attr2->community && attr1->med == attr2->med
+           && bgp_attr_get_community(attr1)
+                               == bgp_attr_get_community(attr2)
+               && attr1->med == attr2->med
            && attr1->local_pref == attr2->local_pref
            && attr1->rmap_change_flags == attr2->rmap_change_flags) {
                if (attr1->aggregator_as == attr2->aggregator_as
@@ -844,19 +845,22 @@ struct attr *bgp_attr_intern(struct attr *attr)
        struct ecommunity *ecomm = NULL;
        struct ecommunity *ipv6_ecomm = NULL;
        struct lcommunity *lcomm = NULL;
+       struct community *comm = NULL;
 
-       /* Intern referenced strucutre. */
+       /* Intern referenced structure. */
        if (attr->aspath) {
                if (!attr->aspath->refcnt)
                        attr->aspath = aspath_intern(attr->aspath);
                else
                        attr->aspath->refcnt++;
        }
-       if (attr->community) {
-               if (!attr->community->refcnt)
-                       attr->community = community_intern(attr->community);
+
+       comm = bgp_attr_get_community(attr);
+       if (comm) {
+               if (!comm->refcnt)
+                       bgp_attr_set_community(attr, community_intern(comm));
                else
-                       attr->community->refcnt++;
+                       comm->refcnt++;
        }
 
        ecomm = bgp_attr_get_ecommunity(attr);
@@ -976,12 +980,16 @@ struct attr *bgp_attr_aggregate_intern(
        struct attr *new;
        int ret;
 
-       memset(&attr, 0, sizeof(struct attr));
+       memset(&attr, 0, sizeof(attr));
 
        /* Origin attribute. */
        attr.origin = origin;
        attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
 
+       /* MED */
+       attr.med = 0;
+       attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
+
        /* AS path attribute. */
        if (aspath)
                attr.aspath = aspath_intern(aspath);
@@ -1003,19 +1011,14 @@ struct attr *bgp_attr_aggregate_intern(
                        community_del_val(community, &gshut);
                }
 
-               attr.community = community;
-               attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
+               bgp_attr_set_community(&attr, community);
        }
 
-       if (ecommunity) {
+       if (ecommunity)
                bgp_attr_set_ecommunity(&attr, ecommunity);
-               attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
-       }
 
-       if (lcommunity) {
+       if (lcommunity)
                bgp_attr_set_lcommunity(&attr, lcommunity);
-               attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
-       }
 
        if (bgp_in_graceful_shutdown(bgp))
                bgp_attr_add_gshut_community(&attr);
@@ -1040,7 +1043,7 @@ struct attr *bgp_attr_aggregate_intern(
                struct attr attr_tmp = attr;
                struct bgp_path_info rmap_path;
 
-               memset(&rmap_path, 0, sizeof(struct bgp_path_info));
+               memset(&rmap_path, 0, sizeof(rmap_path));
                rmap_path.peer = bgp->peer_self;
                rmap_path.attr = &attr_tmp;
 
@@ -1084,28 +1087,26 @@ void bgp_attr_unintern_sub(struct attr *attr)
        struct ecommunity *ipv6_ecomm = NULL;
        struct cluster_list *cluster;
        struct lcommunity *lcomm = NULL;
+       struct community *comm = NULL;
 
        /* aspath refcount shoud be decrement. */
        aspath_unintern(&attr->aspath);
        UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
 
-       if (attr->community)
-               community_unintern(&attr->community);
-       UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
+       comm = bgp_attr_get_community(attr);
+       community_unintern(&comm);
+       bgp_attr_set_community(attr, NULL);
 
        ecomm = bgp_attr_get_ecommunity(attr);
        ecommunity_unintern(&ecomm);
-       UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
        bgp_attr_set_ecommunity(attr, NULL);
 
        ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
        ecommunity_unintern(&ipv6_ecomm);
-       UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES));
        bgp_attr_set_ipv6_ecommunity(attr, NULL);
 
        lcomm = bgp_attr_get_lcommunity(attr);
        lcommunity_unintern(&lcomm);
-       UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
        bgp_attr_set_lcommunity(attr, NULL);
 
        cluster = bgp_attr_get_cluster(attr);
@@ -1171,21 +1172,27 @@ void bgp_attr_flush(struct attr *attr)
        struct ecommunity *ipv6_ecomm;
        struct cluster_list *cluster;
        struct lcommunity *lcomm;
+       struct community *comm;
 
        if (attr->aspath && !attr->aspath->refcnt) {
                aspath_free(attr->aspath);
                attr->aspath = NULL;
        }
-       if (attr->community && !attr->community->refcnt)
-               community_free(&attr->community);
+       comm = bgp_attr_get_community(attr);
+       if (comm && !comm->refcnt)
+               community_free(&comm);
+       bgp_attr_set_community(attr, NULL);
+
        ecomm = bgp_attr_get_ecommunity(attr);
        if (ecomm && !ecomm->refcnt)
                ecommunity_free(&ecomm);
        bgp_attr_set_ecommunity(attr, NULL);
+
        ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
        if (ipv6_ecomm && !ipv6_ecomm->refcnt)
                ecommunity_free(&ipv6_ecomm);
        bgp_attr_set_ipv6_ecommunity(attr, NULL);
+
        lcomm = bgp_attr_get_lcommunity(attr);
        if (lcomm && !lcomm->refcnt)
                lcommunity_free(&lcomm);
@@ -1231,7 +1238,7 @@ void bgp_attr_flush(struct attr *attr)
  * are partial/optional and hence where the error likely was not
  * introduced by the sending neighbour.
  */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
 bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
                   bgp_size_t length)
 {
@@ -1438,7 +1445,8 @@ static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
 }
 
 /* Get origin attribute of the update message. */
-static bgp_attr_parse_ret_t bgp_attr_origin(struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret
+bgp_attr_origin(struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
        struct attr *const attr = args->attr;
@@ -1508,8 +1516,8 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
        return BGP_ATTR_PARSE_PROCEED;
 }
 
-static bgp_attr_parse_ret_t bgp_attr_aspath_check(struct peer *const peer,
-                                                 struct attr *const attr)
+static enum bgp_attr_parse_ret bgp_attr_aspath_check(struct peer *const peer,
+                                                    struct attr *const attr)
 {
        /* These checks were part of bgp_attr_aspath, but with
         * as4 we should to check aspath things when
@@ -1591,8 +1599,8 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
 /*
  * Check that the nexthop attribute is valid.
  */
-bgp_attr_parse_ret_t
-bgp_attr_nexthop_valid(struct peer *peer, struct attr *attr)
+enum bgp_attr_parse_ret bgp_attr_nexthop_valid(struct peer *peer,
+                                              struct attr *attr)
 {
        in_addr_t nexthop_h;
 
@@ -1621,7 +1629,8 @@ bgp_attr_nexthop_valid(struct peer *peer, struct attr *attr)
 }
 
 /* Nexthop attribute. */
-static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret
+bgp_attr_nexthop(struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
        struct attr *const attr = args->attr;
@@ -1643,7 +1652,7 @@ static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args)
 }
 
 /* MED atrribute. */
-static bgp_attr_parse_ret_t bgp_attr_med(struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret bgp_attr_med(struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
        struct attr *const attr = args->attr;
@@ -1666,7 +1675,7 @@ static bgp_attr_parse_ret_t bgp_attr_med(struct bgp_attr_parser_args *args)
 }
 
 /* Local preference attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
 bgp_attr_local_pref(struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
@@ -1778,7 +1787,7 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
 }
 
 /* New Aggregator attribute */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
 bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
                        as_t *as4_aggregator_as,
                        struct in_addr *as4_aggregator_addr)
@@ -1822,7 +1831,7 @@ bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
 
 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
  */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
 bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
                         struct aspath *as4_path, as_t as4_aggregator,
                         struct in_addr *as4_aggregator_addr)
@@ -1924,7 +1933,7 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
 }
 
 /* Community attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
 bgp_attr_community(struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
@@ -1932,13 +1941,14 @@ bgp_attr_community(struct bgp_attr_parser_args *args)
        const bgp_size_t length = args->length;
 
        if (length == 0) {
-               attr->community = NULL;
+               bgp_attr_set_community(attr, NULL);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
                                          args->total);
        }
 
-       attr->community =
-               community_parse((uint32_t *)stream_pnt(peer->curr), length);
+       bgp_attr_set_community(
+               attr,
+               community_parse((uint32_t *)stream_pnt(peer->curr), length));
 
        /* XXX: fix community_parse to use stream API and remove this */
        stream_forward_getp(peer->curr, length);
@@ -1946,17 +1956,15 @@ bgp_attr_community(struct bgp_attr_parser_args *args)
        /* The Community attribute SHALL be considered malformed if its
         * length is not a non-zero multiple of 4.
         */
-       if (!attr->community)
+       if (!bgp_attr_get_community(attr))
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
                                          args->total);
 
-       attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
-
        return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* Originator ID attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
 bgp_attr_originator_id(struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
@@ -1984,7 +1992,7 @@ bgp_attr_originator_id(struct bgp_attr_parser_args *args)
 }
 
 /* Cluster list attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
 bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
@@ -2255,7 +2263,7 @@ int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
 }
 
 /* Large Community attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
 bgp_attr_large_community(struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
@@ -2281,13 +2289,11 @@ bgp_attr_large_community(struct bgp_attr_parser_args *args)
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
                                          args->total);
 
-       attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
-
        return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* Extended Community attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
 bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
@@ -2319,8 +2325,6 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
                                          args->total);
 
-       attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
-
        /* Extract DF election preference and  mobility sequence number */
        attr->df_pref = bgp_attr_df_pref_from_ec(attr, &attr->df_alg);
 
@@ -2363,7 +2367,7 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
 }
 
 /* IPv6 Extended Community attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
@@ -2390,8 +2394,6 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
                                          args->total);
 
-       attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES);
-
        return BGP_ATTR_PARSE_PROCEED;
 }
 
@@ -2528,7 +2530,7 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
 /* SRv6 Service Data Sub-Sub-TLV attribute
  * draft-ietf-bess-srv6-services-07
  */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
 bgp_attr_srv6_service_data(struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
@@ -2559,6 +2561,16 @@ bgp_attr_srv6_service_data(struct bgp_attr_parser_args *args)
                                          args->total);
        }
 
+       if (length < BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
+               flog_err(
+                       EC_BGP_ATTR_LEN,
+                       "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
+                       BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
+                       length);
+               return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                         args->total);
+       }
+
        if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE) {
                loc_block_len = stream_getc(peer->curr);
                loc_node_len = stream_getc(peer->curr);
@@ -2599,7 +2611,7 @@ bgp_attr_srv6_service_data(struct bgp_attr_parser_args *args)
 /* SRv6 Service Sub-TLV attribute
  * draft-ietf-bess-srv6-services-07
  */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
 bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
@@ -2608,7 +2620,7 @@ bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
        uint8_t type, sid_flags;
        uint16_t length, endpoint_behavior;
        size_t headersz = sizeof(type) + sizeof(length);
-       bgp_attr_parse_ret_t err;
+       enum bgp_attr_parse_ret err;
        char buf[BUFSIZ];
 
        if (STREAM_READABLE(peer->curr) < headersz) {
@@ -2694,8 +2706,9 @@ bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
  * Read an individual SID value returning how much data we have read
  * Returns 0 if there was an error that needs to be passed up the stack
  */
-static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length,
-                                             struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret
+bgp_attr_psid_sub(uint8_t type, uint16_t length,
+                 struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
        struct attr *const attr = args->attr;
@@ -2902,11 +2915,11 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length,
 /* Prefix SID attribute
  * draft-ietf-idr-bgp-prefix-sid-05
  */
-bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
+enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
        struct attr *const attr = args->attr;
-       bgp_attr_parse_ret_t ret;
+       enum bgp_attr_parse_ret ret;
 
        attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
 
@@ -2965,7 +2978,7 @@ bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
 /* PMSI tunnel attribute (RFC 6514)
  * Basic validation checks done here.
  */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
 {
        struct peer *const peer = args->peer;
@@ -3013,7 +3026,8 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
 }
 
 /* BGP unknown attribute treatment. */
-static bgp_attr_parse_ret_t bgp_attr_unknown(struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret
+bgp_attr_unknown(struct bgp_attr_parser_args *args)
 {
        bgp_size_t total = args->total;
        struct transit *transit;
@@ -3118,11 +3132,12 @@ static int bgp_attr_check(struct peer *peer, struct attr *attr)
 
 /* Read attribute of update packet.  This function is called from
    bgp_update_receive() in bgp_packet.c.  */
-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)
+enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
+                                      bgp_size_t size,
+                                      struct bgp_nlri *mp_update,
+                                      struct bgp_nlri *mp_withdraw)
 {
-       bgp_attr_parse_ret_t ret;
+       enum bgp_attr_parse_ret ret;
        uint8_t flag = 0;
        uint8_t type = 0;
        bgp_size_t length;
@@ -3581,8 +3596,8 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
                               struct attr *attr)
 {
        size_t sizep;
-       iana_afi_t pkt_afi;
-       iana_safi_t pkt_safi;
+       iana_afi_t pkt_afi = IANA_AFI_IPV4;
+       iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
        afi_t nh_afi;
 
        /* Set extended bit always to encode the attribute length as 2 bytes */
@@ -4075,20 +4090,23 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
        /* Community attribute. */
        if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
            && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
-               if (attr->community->size * 4 > 255) {
+               struct community *comm = NULL;
+
+               comm = bgp_attr_get_community(attr);
+               if (comm->size * 4 > 255) {
                        stream_putc(s,
                                    BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
                                            | BGP_ATTR_FLAG_EXTLEN);
                        stream_putc(s, BGP_ATTR_COMMUNITIES);
-                       stream_putw(s, attr->community->size * 4);
+                       stream_putw(s, comm->size * 4);
                } else {
                        stream_putc(s,
                                    BGP_ATTR_FLAG_OPTIONAL
                                            | BGP_ATTR_FLAG_TRANS);
                        stream_putc(s, BGP_ATTR_COMMUNITIES);
-                       stream_putc(s, attr->community->size * 4);
+                       stream_putc(s, comm->size * 4);
                }
-               stream_put(s, attr->community->val, attr->community->size * 4);
+               stream_put(s, comm->val, comm->size * 4);
        }
 
        /*
@@ -4159,9 +4177,14 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
        if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
            && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
                struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
-
-               if (peer->sort == BGP_PEER_IBGP
-                   || peer->sort == BGP_PEER_CONFED) {
+               bool transparent = CHECK_FLAG(peer->af_flags[afi][safi],
+                                             PEER_FLAG_RSERVER_CLIENT) &&
+                                  from &&
+                                  CHECK_FLAG(from->af_flags[afi][safi],
+                                             PEER_FLAG_RSERVER_CLIENT);
+
+               if (peer->sort == BGP_PEER_IBGP ||
+                   peer->sort == BGP_PEER_CONFED || transparent) {
                        if (ecomm->size * 8 > 255) {
                                stream_putc(s,
                                            BGP_ATTR_FLAG_OPTIONAL
@@ -4381,8 +4404,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
 size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi, safi_t safi)
 {
        unsigned long attrlen_pnt;
-       iana_afi_t pkt_afi;
-       iana_safi_t pkt_safi;
+       iana_afi_t pkt_afi = IANA_AFI_IPV4;
+       iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
 
        /* Set extended bit always to encode the attribute length as 2 bytes */
        stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN);
@@ -4525,20 +4548,23 @@ void bgp_dump_routes_attr(struct stream *s, struct attr *attr,
 
        /* Community attribute. */
        if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
-               if (attr->community->size * 4 > 255) {
+               struct community *comm = NULL;
+
+               comm = bgp_attr_get_community(attr);
+               if (comm->size * 4 > 255) {
                        stream_putc(s,
                                    BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
                                            | BGP_ATTR_FLAG_EXTLEN);
                        stream_putc(s, BGP_ATTR_COMMUNITIES);
-                       stream_putw(s, attr->community->size * 4);
+                       stream_putw(s, comm->size * 4);
                } else {
                        stream_putc(s,
                                    BGP_ATTR_FLAG_OPTIONAL
                                            | BGP_ATTR_FLAG_TRANS);
                        stream_putc(s, BGP_ATTR_COMMUNITIES);
-                       stream_putc(s, attr->community->size * 4);
+                       stream_putc(s, comm->size * 4);
                }
-               stream_put(s, attr->community->val, attr->community->size * 4);
+               stream_put(s, comm->val, comm->size * 4);
        }
 
        /* Large Community attribute. */