diff options
| -rw-r--r-- | bgpd/bgp_evpn.c | 64 | ||||
| -rw-r--r-- | lib/stream.c | 24 | ||||
| -rw-r--r-- | lib/stream.h | 14 |
3 files changed, 72 insertions, 30 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 54593497cc..3bcef1a555 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -3590,11 +3590,12 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi, uint32_t addpath_id) { struct prefix_rd prd; - struct prefix_evpn p; - struct bgp_route_evpn evpn; + struct prefix_evpn p = {}; + struct bgp_route_evpn evpn = {}; uint8_t ipaddr_len; uint8_t macaddr_len; - mpls_label_t label[BGP_MAX_LABELS]; /* holds the VNI(s) as in packet */ + /* holds the VNI(s) as in packet */ + mpls_label_t label[BGP_MAX_LABELS] = {}; uint32_t num_labels = 0; uint32_t eth_tag; int ret; @@ -3613,60 +3614,61 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi, return -1; } - memset(&evpn, 0, sizeof(evpn)); + struct stream *pkt = stream_new(psize); + stream_put(pkt, pfx, psize); /* Make prefix_rd */ prd.family = AF_UNSPEC; prd.prefixlen = 64; - memcpy(&prd.val, pfx, 8); - pfx += 8; + + STREAM_GET(&prd.val, pkt, 8); /* Make EVPN prefix. */ - memset(&p, 0, sizeof(struct prefix_evpn)); p.family = AF_EVPN; p.prefixlen = EVPN_ROUTE_PREFIXLEN; p.prefix.route_type = BGP_EVPN_MAC_IP_ROUTE; /* Copy Ethernet Seg Identifier */ if (attr) { - memcpy(&attr->esi, pfx, sizeof(esi_t)); + STREAM_GET(&attr->esi, pkt, sizeof(esi_t)); + if (bgp_evpn_is_esi_local(&attr->esi)) attr->es_flags |= ATTR_ES_IS_LOCAL; else attr->es_flags &= ~ATTR_ES_IS_LOCAL; + } else { + STREAM_FORWARD_GETP(pkt, sizeof(esi_t)); } - pfx += sizeof(esi_t); /* Copy Ethernet Tag */ - memcpy(ð_tag, pfx, 4); + STREAM_GET(ð_tag, pkt, 4); p.prefix.macip_addr.eth_tag = ntohl(eth_tag); - pfx += 4; /* Get the MAC Addr len */ - macaddr_len = *pfx++; + STREAM_GETC(pkt, macaddr_len); /* Get the MAC Addr */ if (macaddr_len == (ETH_ALEN * 8)) { - memcpy(&p.prefix.macip_addr.mac.octet, pfx, ETH_ALEN); - pfx += ETH_ALEN; + STREAM_GET(&p.prefix.macip_addr.mac.octet, pkt, ETH_ALEN); } else { flog_err( EC_BGP_EVPN_ROUTE_INVALID, "%u:%s - Rx EVPN Type-2 NLRI with unsupported MAC address length %d", peer->bgp->vrf_id, peer->host, macaddr_len); - return -1; + goto fail; } /* Get the IP. */ - ipaddr_len = *pfx++; + STREAM_GETC(pkt, ipaddr_len); + if (ipaddr_len != 0 && ipaddr_len != IPV4_MAX_BITLEN && ipaddr_len != IPV6_MAX_BITLEN) { flog_err( EC_BGP_EVPN_ROUTE_INVALID, "%u:%s - Rx EVPN Type-2 NLRI with unsupported IP address length %d", peer->bgp->vrf_id, peer->host, ipaddr_len); - return -1; + goto fail; } if (ipaddr_len) { @@ -3674,25 +3676,17 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi, p.prefix.macip_addr.ip.ipa_type = (ipaddr_len == IPV4_MAX_BYTELEN) ? IPADDR_V4 : IPADDR_V6; - memcpy(&p.prefix.macip_addr.ip.ip.addr, pfx, ipaddr_len); + STREAM_GET(&p.prefix.macip_addr.ip.ip.addr, pkt, ipaddr_len); } - pfx += ipaddr_len; /* Get the VNI(s). Stored as bytes here. */ + STREAM_GET(&label[0], pkt, BGP_LABEL_BYTES); num_labels++; - memset(label, 0, sizeof(label)); - memcpy(&label[0], pfx, BGP_LABEL_BYTES); - pfx += BGP_LABEL_BYTES; - psize -= (33 + ipaddr_len); + /* Do we have a second VNI? */ - if (psize) { + if (STREAM_READABLE(pkt)) { num_labels++; - memcpy(&label[1], pfx, BGP_LABEL_BYTES); - /* - * If in future, we are required to access additional fields, - * we MUST increment pfx by BGP_LABEL_BYTES in before reading - * the next field - */ + STREAM_GET(&label[1], pkt, BGP_LABEL_BYTES); } /* Process the route. */ @@ -3704,6 +3698,16 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi, ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, &label[0], num_labels, &evpn); + goto done; + +fail: +stream_failure: + flog_err(EC_BGP_EVPN_ROUTE_INVALID, + "%u:%s - Rx EVPN Type-2 NLRI - corrupt, discarding", + peer->bgp->vrf_id, peer->host); + ret = -1; +done: + stream_free(pkt); return ret; } diff --git a/lib/stream.c b/lib/stream.c index 768114e69b..6e62e11380 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -256,6 +256,18 @@ void stream_forward_getp(struct stream *s, size_t size) s->getp += size; } +bool stream_forward_getp2(struct stream *s, size_t size) +{ + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID(s, s->getp + size)) + return false; + + s->getp += size; + + return true; +} + void stream_forward_endp(struct stream *s, size_t size) { STREAM_VERIFY_SANE(s); @@ -268,6 +280,18 @@ void stream_forward_endp(struct stream *s, size_t size) s->endp += size; } +bool stream_forward_endp2(struct stream *s, size_t size) +{ + STREAM_VERIFY_SANE(s); + + if (!ENDP_VALID(s, s->endp + size)) + return false; + + s->endp += size; + + return true; +} + /* Copy from stream to destination. */ bool stream_get2(void *dst, struct stream *s, size_t size) { diff --git a/lib/stream.h b/lib/stream.h index 1250b6944d..f2c16b3486 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -173,7 +173,9 @@ extern struct stream *stream_dupcat(const struct stream *s1, extern void stream_set_getp(struct stream *, size_t); extern void stream_set_endp(struct stream *, size_t); extern void stream_forward_getp(struct stream *, size_t); +extern bool stream_forward_getp2(struct stream *, size_t); extern void stream_forward_endp(struct stream *, size_t); +extern bool stream_forward_endp2(struct stream *, size_t); /* steam_put: NULL source zeroes out size_t bytes of stream */ extern void stream_put(struct stream *, const void *, size_t); @@ -453,6 +455,18 @@ static inline const uint8_t *ptr_get_be32(const uint8_t *ptr, uint32_t *out) goto stream_failure; \ } while (0) +#define STREAM_FORWARD_GETP(STR, SIZE) \ + do { \ + if (!stream_forward_getp2((STR), (SIZE))) \ + goto stream_failure; \ + } while (0) + +#define STREAM_FORWARD_ENDP(STR, SIZE) \ + do { \ + if (!stream_forward_endp2((STR), (SIZE))) \ + goto stream_failure; \ + } while (0) + #ifdef __cplusplus } #endif |
