mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-29 23:09:34 +00:00
Merge pull request #5744 from ton31337/fix/thread-as-withdraw_attributes
bgpd: Update some attributes how they are handled if malformed
This commit is contained in:
commit
35f50b9305
@ -1176,7 +1176,7 @@ bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
|
|||||||
return BGP_ATTR_PARSE_PROCEED;
|
return BGP_ATTR_PARSE_PROCEED;
|
||||||
|
|
||||||
/* Core attributes, particularly ones which may influence route
|
/* Core attributes, particularly ones which may influence route
|
||||||
* selection, should always cause session resets
|
* selection, should be treat-as-withdraw.
|
||||||
*/
|
*/
|
||||||
case BGP_ATTR_ORIGIN:
|
case BGP_ATTR_ORIGIN:
|
||||||
case BGP_ATTR_AS_PATH:
|
case BGP_ATTR_AS_PATH:
|
||||||
@ -1184,11 +1184,13 @@ bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
|
|||||||
case BGP_ATTR_MULTI_EXIT_DISC:
|
case BGP_ATTR_MULTI_EXIT_DISC:
|
||||||
case BGP_ATTR_LOCAL_PREF:
|
case BGP_ATTR_LOCAL_PREF:
|
||||||
case BGP_ATTR_COMMUNITIES:
|
case BGP_ATTR_COMMUNITIES:
|
||||||
|
case BGP_ATTR_EXT_COMMUNITIES:
|
||||||
|
case BGP_ATTR_LARGE_COMMUNITIES:
|
||||||
case BGP_ATTR_ORIGINATOR_ID:
|
case BGP_ATTR_ORIGINATOR_ID:
|
||||||
case BGP_ATTR_CLUSTER_LIST:
|
case BGP_ATTR_CLUSTER_LIST:
|
||||||
|
return BGP_ATTR_PARSE_WITHDRAW;
|
||||||
case BGP_ATTR_MP_REACH_NLRI:
|
case BGP_ATTR_MP_REACH_NLRI:
|
||||||
case BGP_ATTR_MP_UNREACH_NLRI:
|
case BGP_ATTR_MP_UNREACH_NLRI:
|
||||||
case BGP_ATTR_EXT_COMMUNITIES:
|
|
||||||
bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, subcode,
|
bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, subcode,
|
||||||
notify_datap, length);
|
notify_datap, length);
|
||||||
return BGP_ATTR_PARSE_ERROR;
|
return BGP_ATTR_PARSE_ERROR;
|
||||||
@ -1421,9 +1423,7 @@ static bgp_attr_parse_ret_t bgp_attr_aspath_check(struct peer *const peer,
|
|||||||
&& aspath_confed_check(attr->aspath))) {
|
&& aspath_confed_check(attr->aspath))) {
|
||||||
flog_err(EC_BGP_ATTR_MAL_AS_PATH, "Malformed AS path from %s",
|
flog_err(EC_BGP_ATTR_MAL_AS_PATH, "Malformed AS path from %s",
|
||||||
peer->host);
|
peer->host);
|
||||||
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
|
return BGP_ATTR_PARSE_WITHDRAW;
|
||||||
BGP_NOTIFY_UPDATE_MAL_AS_PATH);
|
|
||||||
return BGP_ATTR_PARSE_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First AS check for EBGP. */
|
/* First AS check for EBGP. */
|
||||||
@ -1433,9 +1433,7 @@ static bgp_attr_parse_ret_t bgp_attr_aspath_check(struct peer *const peer,
|
|||||||
flog_err(EC_BGP_ATTR_FIRST_AS,
|
flog_err(EC_BGP_ATTR_FIRST_AS,
|
||||||
"%s incorrect first AS (must be %u)",
|
"%s incorrect first AS (must be %u)",
|
||||||
peer->host, peer->as);
|
peer->host, peer->as);
|
||||||
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
|
return BGP_ATTR_PARSE_WITHDRAW;
|
||||||
BGP_NOTIFY_UPDATE_MAL_AS_PATH);
|
|
||||||
return BGP_ATTR_PARSE_ERROR;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1562,8 +1560,12 @@ bgp_attr_local_pref(struct bgp_attr_parser_args *args)
|
|||||||
struct attr *const attr = args->attr;
|
struct attr *const attr = args->attr;
|
||||||
const bgp_size_t length = args->length;
|
const bgp_size_t length = args->length;
|
||||||
|
|
||||||
/* Length check. */
|
/* if received from an internal neighbor, it SHALL be considered
|
||||||
if (length != 4) {
|
* malformed if its length is not equal to 4. If malformed, the
|
||||||
|
* UPDATE message SHALL be handled using the approach of "treat-as-
|
||||||
|
* withdraw".
|
||||||
|
*/
|
||||||
|
if (peer->sort == BGP_PEER_IBGP && length != 4) {
|
||||||
flog_err(EC_BGP_ATTR_LEN,
|
flog_err(EC_BGP_ATTR_LEN,
|
||||||
"LOCAL_PREF attribute length isn't 4 [%u]", length);
|
"LOCAL_PREF attribute length isn't 4 [%u]", length);
|
||||||
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
|
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
|
||||||
@ -1617,7 +1619,8 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
|
|||||||
int wantedlen = 6;
|
int wantedlen = 6;
|
||||||
|
|
||||||
/* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
|
/* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
|
||||||
if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV))
|
if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
|
||||||
|
&& CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV))
|
||||||
wantedlen = 8;
|
wantedlen = 8;
|
||||||
|
|
||||||
if (length != wantedlen) {
|
if (length != wantedlen) {
|
||||||
@ -1792,6 +1795,9 @@ bgp_attr_community(struct bgp_attr_parser_args *args)
|
|||||||
/* XXX: fix community_parse to use stream API and remove this */
|
/* XXX: fix community_parse to use stream API and remove this */
|
||||||
stream_forward_getp(peer->curr, length);
|
stream_forward_getp(peer->curr, length);
|
||||||
|
|
||||||
|
/* The Community attribute SHALL be considered malformed if its
|
||||||
|
* length is not a non-zero multiple of 4.
|
||||||
|
*/
|
||||||
if (!attr->community)
|
if (!attr->community)
|
||||||
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
|
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
|
||||||
args->total);
|
args->total);
|
||||||
@ -1809,7 +1815,11 @@ bgp_attr_originator_id(struct bgp_attr_parser_args *args)
|
|||||||
struct attr *const attr = args->attr;
|
struct attr *const attr = args->attr;
|
||||||
const bgp_size_t length = args->length;
|
const bgp_size_t length = args->length;
|
||||||
|
|
||||||
/* Length check. */
|
/* if received from an internal neighbor, it SHALL be considered
|
||||||
|
* malformed if its length is not equal to 4. If malformed, the
|
||||||
|
* UPDATE message SHALL be handled using the approach of "treat-as-
|
||||||
|
* withdraw".
|
||||||
|
*/
|
||||||
if (length != 4) {
|
if (length != 4) {
|
||||||
flog_err(EC_BGP_ATTR_LEN, "Bad originator ID length %d",
|
flog_err(EC_BGP_ATTR_LEN, "Bad originator ID length %d",
|
||||||
length);
|
length);
|
||||||
@ -1833,7 +1843,11 @@ bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
|
|||||||
struct attr *const attr = args->attr;
|
struct attr *const attr = args->attr;
|
||||||
const bgp_size_t length = args->length;
|
const bgp_size_t length = args->length;
|
||||||
|
|
||||||
/* Check length. */
|
/* if received from an internal neighbor, it SHALL be considered
|
||||||
|
* malformed if its length is not a non-zero multiple of 4. If
|
||||||
|
* malformed, the UPDATE message SHALL be handled using the approach
|
||||||
|
* of "treat-as-withdraw".
|
||||||
|
*/
|
||||||
if (length % 4) {
|
if (length % 4) {
|
||||||
flog_err(EC_BGP_ATTR_LEN, "Bad cluster list length %d", length);
|
flog_err(EC_BGP_ATTR_LEN, "Bad cluster list length %d", length);
|
||||||
|
|
||||||
@ -2150,6 +2164,9 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
|
|||||||
/* XXX: fix ecommunity_parse to use stream API */
|
/* XXX: fix ecommunity_parse to use stream API */
|
||||||
stream_forward_getp(peer->curr, length);
|
stream_forward_getp(peer->curr, length);
|
||||||
|
|
||||||
|
/* The Extended Community attribute SHALL be considered malformed if
|
||||||
|
* its length is not a non-zero multiple of 8.
|
||||||
|
*/
|
||||||
if (!attr->ecommunity)
|
if (!attr->ecommunity)
|
||||||
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
|
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
|
||||||
args->total);
|
args->total);
|
||||||
@ -2754,14 +2771,14 @@ static int bgp_attr_check(struct peer *peer, struct attr *attr)
|
|||||||
&& !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))
|
&& !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))
|
||||||
type = BGP_ATTR_LOCAL_PREF;
|
type = BGP_ATTR_LOCAL_PREF;
|
||||||
|
|
||||||
|
/* If any of the well-known mandatory attributes are not present
|
||||||
|
* in an UPDATE message, then "treat-as-withdraw" MUST be used.
|
||||||
|
*/
|
||||||
if (type) {
|
if (type) {
|
||||||
flog_warn(EC_BGP_MISSING_ATTRIBUTE,
|
flog_warn(EC_BGP_MISSING_ATTRIBUTE,
|
||||||
"%s Missing well-known attribute %s.", peer->host,
|
"%s Missing well-known attribute %s.", peer->host,
|
||||||
lookup_msg(attr_str, type, NULL));
|
lookup_msg(attr_str, type, NULL));
|
||||||
bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
|
return BGP_ATTR_PARSE_WITHDRAW;
|
||||||
BGP_NOTIFY_UPDATE_MISS_ATTR, &type,
|
|
||||||
1);
|
|
||||||
return BGP_ATTR_PARSE_ERROR;
|
|
||||||
}
|
}
|
||||||
return BGP_ATTR_PARSE_PROCEED;
|
return BGP_ATTR_PARSE_PROCEED;
|
||||||
}
|
}
|
||||||
|
@ -653,7 +653,7 @@ static struct aspath_tests {
|
|||||||
&test_segments[6],
|
&test_segments[6],
|
||||||
NULL,
|
NULL,
|
||||||
AS4_DATA,
|
AS4_DATA,
|
||||||
-1,
|
-2,
|
||||||
PEER_CAP_AS4_ADV,
|
PEER_CAP_AS4_ADV,
|
||||||
{
|
{
|
||||||
COMMON_ATTRS,
|
COMMON_ATTRS,
|
||||||
|
Loading…
Reference in New Issue
Block a user