From 37b01a7a68f19d84d2c60f96e9dab3296b39c26a Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 15 Apr 2019 23:53:20 +0300 Subject: [PATCH] bgpd: Do not send UPDATE message with maximum-prefix When using maximum-prefix and count is overflow BGP sends UPDATE message: Apr 15 20:45:06 exit1-debian-9 bgpd[9818]: 192.168.0.2 [Error] Error parsing NLRI Apr 15 20:45:06 exit1-debian-9 bgpd[9818]: %NOTIFICATION: sent to neighbor 192.168.0.2 3/10 (UPDATE Message Error/Invalid Network Field) 0 bytes Signed-off-by: Donatas Abraitis --- bgpd/bgp_evpn.c | 18 +++++++++--------- bgpd/bgp_flowspec.c | 14 +++++++------- bgpd/bgp_label.c | 12 ++++++------ bgpd/bgp_mplsvpn.c | 12 ++++++------ bgpd/bgp_packet.c | 7 ++++--- bgpd/bgp_route.c | 22 +++++++++++++--------- bgpd/bgp_route.h | 18 ++++++++++++++++++ 7 files changed, 63 insertions(+), 40 deletions(-) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 7ee920aba8..4810b73bc7 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -4694,7 +4694,7 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, if (addpath_encoded) { /* When packet overflow occurs return immediately. */ if (pnt + BGP_ADDPATH_ID_LEN > lim) - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW; addpath_id = ntohl(*((uint32_t *)pnt)); pnt += BGP_ADDPATH_ID_LEN; @@ -4702,14 +4702,14 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, /* All EVPN NLRI types start with type and length. */ if (pnt + 2 > lim) - return -1; + return BGP_NLRI_PARSE_ERROR_EVPN_MISSING_TYPE; rtype = *pnt++; psize = *pnt++; /* When packet overflow occur return immediately. */ if (pnt + psize > lim) - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW; switch (rtype) { case BGP_EVPN_MAC_IP_ROUTE: @@ -4720,7 +4720,7 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, BGP_ERR_EVPN_FAIL, "%u:%s - Error in processing EVPN type-2 NLRI size %d", peer->bgp->vrf_id, peer->host, psize); - return -1; + return BGP_NLRI_PARSE_ERROR_EVPN_TYPE2_SIZE; } break; @@ -4732,7 +4732,7 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, BGP_ERR_PKT_PROCESS, "%u:%s - Error in processing EVPN type-3 NLRI size %d", peer->bgp->vrf_id, peer->host, psize); - return -1; + return BGP_NLRI_PARSE_ERROR_EVPN_TYPE3_SIZE; } break; @@ -4744,7 +4744,7 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, BGP_ERR_PKT_PROCESS, "%u:%s - Error in processing EVPN type-4 NLRI size %d", peer->bgp->vrf_id, peer->host, psize); - return -1; + return BGP_NLRI_PARSE_ERROR_EVPN_TYPE4_SIZE; } break; @@ -4755,7 +4755,7 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, BGP_ERR_PKT_PROCESS, "%u:%s - Error in processing EVPN type-5 NLRI size %d", peer->bgp->vrf_id, peer->host, psize); - return -1; + return BGP_NLRI_PARSE_ERROR_EVPN_TYPE5_SIZE; } break; @@ -4766,9 +4766,9 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, /* Packet length consistency check. */ if (pnt != lim) - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH; - return 0; + return BGP_NLRI_PARSE_OK; } /* diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c index e29508bf36..418ad7c48a 100644 --- a/bgpd/bgp_flowspec.c +++ b/bgpd/bgp_flowspec.c @@ -106,14 +106,14 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, if (afi == AFI_IP6) { flog_err(LIB_ERR_DEVELOPMENT, "BGP flowspec IPv6 not supported"); - return -1; + return BGP_NLRI_PARSE_ERROR_FLOWSPEC_IPV6_NOT_SUPPORTED; } if (packet->length >= FLOWSPEC_NLRI_SIZELIMIT) { flog_err(BGP_ERR_FLOWSPEC_PACKET, "BGP flowspec nlri length maximum reached (%u)", packet->length); - return -1; + return BGP_NLRI_PARSE_ERROR_FLOWSPEC_NLRI_SIZELIMIT; } for (; pnt < lim; pnt += psize) { @@ -122,7 +122,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, /* All FlowSpec NLRI begin with length. */ if (pnt + 1 > lim) - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW; psize = *pnt++; @@ -131,12 +131,12 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, flog_err(BGP_ERR_FLOWSPEC_PACKET, "Flowspec NLRI length inconsistent ( size %u seen)", psize); - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW; } if (bgp_fs_nlri_validate(pnt, psize) < 0) { flog_err(BGP_ERR_FLOWSPEC_PACKET, "Bad flowspec format or NLRI options not supported"); - return -1; + return BGP_NLRI_PARSE_ERROR_FLOWSPEC_BAD_FORMAT; } p.family = AF_FLOWSPEC; p.prefixlen = 0; @@ -191,8 +191,8 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, flog_err(BGP_ERR_FLOWSPEC_INSTALLATION, "Flowspec NLRI failed to be %s.", attr ? "added" : "withdrawn"); - return -1; + return BGP_NLRI_PARSE_ERROR; } } - return 0; + return BGP_NLRI_PARSE_OK; } diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c index 633e589333..a93cafcb25 100644 --- a/bgpd/bgp_label.c +++ b/bgpd/bgp_label.c @@ -232,7 +232,7 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr, /* When packet overflow occurs return immediately. */ if (pnt + BGP_ADDPATH_ID_LEN > lim) - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW; addpath_id = ntohl(*((uint32_t *)pnt)); pnt += BGP_ADDPATH_ID_LEN; @@ -249,7 +249,7 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr, BGP_ERR_UPDATE_RCV, "%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)", peer->host, prefixlen, (uint)(lim - pnt)); - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW; } /* Fill in the labels */ @@ -264,12 +264,12 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr, peer->host, prefixlen); bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_INVAL_NETWORK); - return -1; + return BGP_NLRI_PARSE_ERROR_LABEL_LENGTH; } if ((afi == AFI_IP && p.prefixlen > 32) || (afi == AFI_IP6 && p.prefixlen > 128)) - return -1; + return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH; /* Fetch prefix from NLRI packet */ memcpy(&p.u.prefix, pnt + llen, psize - llen); @@ -340,8 +340,8 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr, BGP_ERR_UPDATE_RCV, "%s [Error] Update packet error / L-U (%zu data remaining after parsing)", peer->host, lim - pnt); - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH; } - return 0; + return BGP_NLRI_PARSE_OK; } diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index b89edfe459..4fff2faa7e 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -139,7 +139,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr, /* When packet overflow occurs return immediately. */ if (pnt + BGP_ADDPATH_ID_LEN > lim) - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW; addpath_id = ntohl(*((uint32_t *)pnt)); pnt += BGP_ADDPATH_ID_LEN; @@ -155,7 +155,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr, BGP_ERR_UPDATE_RCV, "%s [Error] Update packet error / VPN (prefix length %d less than VPN min length)", peer->host, prefixlen); - return -1; + return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH; } /* sanity check against packet data */ @@ -164,7 +164,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr, BGP_ERR_UPDATE_RCV, "%s [Error] Update packet error / VPN (prefix length %d exceeds packet size %u)", peer->host, prefixlen, (uint)(lim - pnt)); - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW; } /* sanity check against storage for the IP address portion */ @@ -175,7 +175,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr, peer->host, prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8, sizeof(p.u)); - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH; } /* Sanity check against max bitlen of the address family */ @@ -186,7 +186,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr, peer->host, prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8, p.family, prefix_blen(&p)); - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH; } /* Copy label to prefix. */ @@ -245,7 +245,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr, BGP_ERR_UPDATE_RCV, "%s [Error] Update packet error / VPN (%zu data remaining after parsing)", peer->host, lim - pnt); - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH; } return 0; diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 6cbb2ec068..8c709f57f2 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -308,7 +308,7 @@ int bgp_nlri_parse(struct peer *peer, struct attr *attr, case SAFI_FLOWSPEC: return bgp_nlri_parse_flowspec(peer, attr, packet, mp_withdraw); } - return -1; + return BGP_NLRI_PARSE_ERROR; } /* @@ -1568,10 +1568,11 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size) nlri_ret = bgp_nlri_parse(peer, &attr, &nlris[i], 1); break; default: - nlri_ret = -1; + nlri_ret = BGP_NLRI_PARSE_ERROR; } - if (nlri_ret < 0) { + if (nlri_ret < BGP_NLRI_PARSE_OK + && nlri_ret != BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW) { flog_err(BGP_ERR_UPDATE_RCV, "%s [Error] Error parsing NLRI", peer->host); if (peer->status == Established) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 7d46d5309e..fead5fe75f 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -4202,7 +4202,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr, /* When packet overflow occurs return immediately. */ if (pnt + BGP_ADDPATH_ID_LEN > lim) - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW; addpath_id = ntohl(*((uint32_t *)pnt)); pnt += BGP_ADDPATH_ID_LEN; @@ -4220,7 +4220,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr, BGP_ERR_UPDATE_RCV, "%s [Error] Update packet error (wrong prefix length %d for afi %u)", peer->host, p.prefixlen, packet->afi); - return -1; + return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH; } /* Packet size overflow check. */ @@ -4232,7 +4232,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr, BGP_ERR_UPDATE_RCV, "%s [Error] Update packet error (prefix length %d overflows packet)", peer->host, p.prefixlen); - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW; } /* Defensive coding, double-check the psize fits in a struct @@ -4242,7 +4242,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr, BGP_ERR_UPDATE_RCV, "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)", peer->host, p.prefixlen, sizeof(p.u)); - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH; } /* Fetch prefix from NLRI packet. */ @@ -4307,10 +4307,14 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr, BGP_ROUTE_NORMAL, NULL, NULL, 0, NULL); - /* Address family configuration mismatch or maximum-prefix count - overflow. */ + /* Do not send BGP notification twice when maximum-prefix count + * overflow. */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)) + return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW; + + /* Address family configuration mismatch. */ if (ret < 0) - return -1; + return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY; } /* Packet length consistency check. */ @@ -4319,10 +4323,10 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr, BGP_ERR_UPDATE_RCV, "%s [Error] Update packet error (prefix length mismatch with total length)", peer->host); - return -1; + return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH; } - return 0; + return BGP_NLRI_PARSE_OK; } static struct bgp_static *bgp_static_new(void) diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index dfef9a8f79..534dd76215 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -72,6 +72,24 @@ enum bgp_show_adj_route_type { */ #define BGP_MAX_LABELS 2 +/* Error codes for handling NLRI */ +#define BGP_NLRI_PARSE_OK 0 +#define BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW -1 +#define BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW -2 +#define BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH -3 +#define BGP_NLRI_PARSE_ERROR_PACKET_LENGTH -4 +#define BGP_NLRI_PARSE_ERROR_LABEL_LENGTH -5 +#define BGP_NLRI_PARSE_ERROR_EVPN_MISSING_TYPE -6 +#define BGP_NLRI_PARSE_ERROR_EVPN_TYPE2_SIZE -7 +#define BGP_NLRI_PARSE_ERROR_EVPN_TYPE3_SIZE -8 +#define BGP_NLRI_PARSE_ERROR_EVPN_TYPE4_SIZE -9 +#define BGP_NLRI_PARSE_ERROR_EVPN_TYPE5_SIZE -10 +#define BGP_NLRI_PARSE_ERROR_FLOWSPEC_IPV6_NOT_SUPPORTED -11 +#define BGP_NLRI_PARSE_ERROR_FLOWSPEC_NLRI_SIZELIMIT -12 +#define BGP_NLRI_PARSE_ERROR_FLOWSPEC_BAD_FORMAT -13 +#define BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY -14 +#define BGP_NLRI_PARSE_ERROR -32 + /* Ancillary information to struct bgp_info, * used for uncommonly used data (aggregation, MPLS, etc.) * and lazily allocated to save memory. -- 2.39.5