diff options
Diffstat (limited to 'bgpd/bgp_open.c')
| -rw-r--r-- | bgpd/bgp_open.c | 353 |
1 files changed, 208 insertions, 145 deletions
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 0dd5463979..4037fd8aef 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -27,25 +27,24 @@ #include "bgpd/bgp_vty.h" #include "bgpd/bgp_memory.h" -static const struct message capcode_str[] = { - {CAPABILITY_CODE_MP, "MultiProtocol Extensions"}, - {CAPABILITY_CODE_REFRESH, "Route Refresh"}, - {CAPABILITY_CODE_ORF, "Cooperative Route Filtering"}, - {CAPABILITY_CODE_RESTART, "Graceful Restart"}, - {CAPABILITY_CODE_AS4, "4-octet AS number"}, - {CAPABILITY_CODE_ADDPATH, "AddPath"}, - {CAPABILITY_CODE_DYNAMIC, "Dynamic"}, - {CAPABILITY_CODE_ENHE, "Extended Next Hop Encoding"}, - {CAPABILITY_CODE_DYNAMIC_OLD, "Dynamic (Old)"}, - {CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)"}, - {CAPABILITY_CODE_ORF_OLD, "ORF (Old)"}, - {CAPABILITY_CODE_FQDN, "FQDN"}, - {CAPABILITY_CODE_ENHANCED_RR, "Enhanced Route Refresh"}, - {CAPABILITY_CODE_EXT_MESSAGE, "BGP Extended Message"}, - {CAPABILITY_CODE_LLGR, "Long-lived BGP Graceful Restart"}, - {CAPABILITY_CODE_ROLE, "Role"}, - {CAPABILITY_CODE_SOFT_VERSION, "Software Version"}, - {0}}; +const struct message capcode_str[] = { + { CAPABILITY_CODE_MP, "MultiProtocol Extensions" }, + { CAPABILITY_CODE_REFRESH, "Route Refresh" }, + { CAPABILITY_CODE_ORF, "Cooperative Route Filtering" }, + { CAPABILITY_CODE_RESTART, "Graceful Restart" }, + { CAPABILITY_CODE_AS4, "4-octet AS number" }, + { CAPABILITY_CODE_ADDPATH, "AddPath" }, + { CAPABILITY_CODE_DYNAMIC, "Dynamic" }, + { CAPABILITY_CODE_ENHE, "Extended Next Hop Encoding" }, + { CAPABILITY_CODE_FQDN, "FQDN" }, + { CAPABILITY_CODE_ENHANCED_RR, "Enhanced Route Refresh" }, + { CAPABILITY_CODE_EXT_MESSAGE, "BGP Extended Message" }, + { CAPABILITY_CODE_LLGR, "Long-lived BGP Graceful Restart" }, + { CAPABILITY_CODE_ROLE, "Role" }, + { CAPABILITY_CODE_SOFT_VERSION, "Software Version" }, + { CAPABILITY_CODE_PATHS_LIMIT, "Paths-Limit" }, + { 0 } +}; /* Minimum sizes for length field of each cap (so not inc. the header) */ static const size_t cap_minsizes[] = { @@ -56,16 +55,14 @@ static const size_t cap_minsizes[] = { [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN, [CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN, [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN, - [CAPABILITY_CODE_DYNAMIC_OLD] = CAPABILITY_CODE_DYNAMIC_LEN, [CAPABILITY_CODE_ENHE] = CAPABILITY_CODE_ENHE_LEN, - [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN, - [CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN, [CAPABILITY_CODE_FQDN] = CAPABILITY_CODE_MIN_FQDN_LEN, [CAPABILITY_CODE_ENHANCED_RR] = CAPABILITY_CODE_ENHANCED_LEN, [CAPABILITY_CODE_EXT_MESSAGE] = CAPABILITY_CODE_EXT_MESSAGE_LEN, [CAPABILITY_CODE_LLGR] = CAPABILITY_CODE_LLGR_LEN, [CAPABILITY_CODE_ROLE] = CAPABILITY_CODE_ROLE_LEN, [CAPABILITY_CODE_SOFT_VERSION] = CAPABILITY_CODE_SOFT_VERSION_LEN, + [CAPABILITY_CODE_PATHS_LIMIT] = CAPABILITY_CODE_PATHS_LIMIT_LEN, }; /* value the capability must be a multiple of. @@ -81,16 +78,14 @@ static const size_t cap_modsizes[] = { [CAPABILITY_CODE_AS4] = 4, [CAPABILITY_CODE_ADDPATH] = 4, [CAPABILITY_CODE_DYNAMIC] = 1, - [CAPABILITY_CODE_DYNAMIC_OLD] = 1, [CAPABILITY_CODE_ENHE] = 6, - [CAPABILITY_CODE_REFRESH_OLD] = 1, - [CAPABILITY_CODE_ORF_OLD] = 1, [CAPABILITY_CODE_FQDN] = 1, [CAPABILITY_CODE_ENHANCED_RR] = 1, [CAPABILITY_CODE_EXT_MESSAGE] = 1, [CAPABILITY_CODE_LLGR] = 1, [CAPABILITY_CODE_ROLE] = 1, [CAPABILITY_CODE_SOFT_VERSION] = 1, + [CAPABILITY_CODE_PATHS_LIMIT] = 5, }; /* BGP-4 Multiprotocol Extentions lead us to the complex world. We can @@ -348,16 +343,14 @@ static void bgp_capability_orf_not_support(struct peer *peer, iana_afi_t afi, peer->host, afi, safi, type, mode); } -static const struct message orf_type_str[] = { - {ORF_TYPE_RESERVED, "Reserved"}, - {ORF_TYPE_PREFIX, "Prefixlist"}, - {ORF_TYPE_PREFIX_OLD, "Prefixlist (old)"}, - {0}}; +const struct message orf_type_str[] = { { ORF_TYPE_RESERVED, "Reserved" }, + { ORF_TYPE_PREFIX, "Prefixlist" }, + { 0 } }; -static const struct message orf_mode_str[] = {{ORF_MODE_RECEIVE, "Receive"}, - {ORF_MODE_SEND, "Send"}, - {ORF_MODE_BOTH, "Both"}, - {0}}; +const struct message orf_mode_str[] = { { ORF_MODE_RECEIVE, "Receive" }, + { ORF_MODE_SEND, "Send" }, + { ORF_MODE_BOTH, "Both" }, + { 0 } }; static int bgp_capability_orf_entry(struct peer *peer, struct capability_header *hdr) @@ -401,7 +394,7 @@ static int bgp_capability_orf_entry(struct peer *peer, zlog_info( "%s ORF Capability entry length error, Cap length %u, num %u", peer->host, hdr->length, num); - bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send(peer->connection, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); return -1; } @@ -440,22 +433,6 @@ static int bgp_capability_orf_entry(struct peer *peer, continue; } break; - case CAPABILITY_CODE_ORF_OLD: - switch (type) { - case ORF_TYPE_RESERVED: - if (bgp_debug_neighbor_events(peer)) - zlog_debug( - "%s Addr-family %d/%d has reserved ORF type, ignoring", - peer->host, afi, safi); - break; - case ORF_TYPE_PREFIX_OLD: - break; - default: - bgp_capability_orf_not_support( - peer, pkt_afi, pkt_safi, type, mode); - continue; - } - break; default: bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi, type, mode); @@ -482,9 +459,6 @@ static int bgp_capability_orf_entry(struct peer *peer, if (hdr->code == CAPABILITY_CODE_ORF) { sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV; rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV; - } else if (hdr->code == CAPABILITY_CODE_ORF_OLD) { - sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV; - rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV; } else { bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi, type, mode); @@ -604,18 +578,6 @@ static int bgp_capability_restart(struct peer *peer, static int bgp_capability_llgr(struct peer *peer, struct capability_header *caphdr) { -/* - * +--------------------------------------------------+ - * | Address Family Identifier (16 bits) | - * +--------------------------------------------------+ - * | Subsequent Address Family Identifier (8 bits) | - * +--------------------------------------------------+ - * | Flags for Address Family (8 bits) | - * +--------------------------------------------------+ - * | Long-lived Stale Time (24 bits) | - * +--------------------------------------------------+ - */ -#define BGP_CAP_LLGR_MIN_PACKET_LEN 7 struct stream *s = BGP_INPUT(peer); size_t end = stream_get_getp(s) + caphdr->length; @@ -663,17 +625,17 @@ static int bgp_capability_llgr(struct peer *peer, /* Unlike other capability parsing routines, this one returns 0 on error */ static as_t bgp_capability_as4(struct peer *peer, struct capability_header *hdr) { - SET_FLAG(peer->cap, PEER_CAP_AS4_RCV); - if (hdr->length != CAPABILITY_CODE_AS4_LEN) { flog_err(EC_BGP_PKT_OPEN, "%s AS4 capability has incorrect data length %d", peer->host, hdr->length); - return 0; + return -1; } as_t as4 = stream_getl(BGP_INPUT(peer)); + SET_FLAG(peer->cap, PEER_CAP_AS4_RCV); + if (BGP_DEBUG(as4, AS4)) zlog_debug( "%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u", @@ -703,10 +665,8 @@ static int bgp_capability_addpath(struct peer *peer, struct stream *s = BGP_INPUT(peer); size_t end = stream_get_getp(s) + hdr->length; - SET_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV); - /* Verify length is a multiple of 4 */ - if (hdr->length % 4) { + if (hdr->length % CAPABILITY_CODE_ADDPATH_LEN) { flog_warn( EC_BGP_CAPABILITY_INVALID_LENGTH, "Add Path: Received invalid length %d, non-multiple of 4", @@ -714,23 +674,38 @@ static int bgp_capability_addpath(struct peer *peer, return -1; } - while (stream_get_getp(s) + 4 <= end) { + SET_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV); + + while (stream_get_getp(s) + CAPABILITY_CODE_ADDPATH_LEN <= end) { afi_t afi; safi_t safi; iana_afi_t pkt_afi = stream_getw(s); iana_safi_t pkt_safi = stream_getc(s); uint8_t send_receive = stream_getc(s); + /* If any other value (other than 1-3) is received, then + * the capability SHOULD be treated as not understood + * and ignored. + */ + if (!send_receive || send_receive > 3) { + flog_warn(EC_BGP_CAPABILITY_INVALID_DATA, + "Add Path: Received invalid send/receive value %u in Add Path capability", + send_receive); + continue; + } + if (bgp_debug_neighbor_events(peer)) - zlog_debug( - "%s OPEN has %s capability for afi/safi: %s/%s%s%s", - peer->host, - lookup_msg(capcode_str, hdr->code, NULL), - iana_afi2str(pkt_afi), iana_safi2str(pkt_safi), - (send_receive & BGP_ADDPATH_RX) ? ", receive" - : "", - (send_receive & BGP_ADDPATH_TX) ? ", transmit" - : ""); + zlog_debug("%s OPEN has %s capability for afi/safi: %s/%s%s%s", + peer->host, + lookup_msg(capcode_str, hdr->code, NULL), + iana_afi2str(pkt_afi), + iana_safi2str(pkt_safi), + CHECK_FLAG(send_receive, BGP_ADDPATH_RX) + ? ", receive" + : "", + CHECK_FLAG(send_receive, BGP_ADDPATH_TX) + ? ", transmit" + : ""); /* Convert AFI, SAFI to internal values, check. */ if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { @@ -749,13 +724,75 @@ static int bgp_capability_addpath(struct peer *peer, continue; } - if (send_receive & BGP_ADDPATH_RX) + if (CHECK_FLAG(send_receive, BGP_ADDPATH_RX)) SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_RCV); + else + UNSET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_RX_RCV); - if (send_receive & BGP_ADDPATH_TX) + if (CHECK_FLAG(send_receive, BGP_ADDPATH_TX)) SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV); + else + UNSET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_TX_RCV); + } + + return 0; +} + +static int bgp_capability_paths_limit(struct peer *peer, + struct capability_header *hdr) +{ + struct stream *s = BGP_INPUT(peer); + size_t end = stream_get_getp(s) + hdr->length; + + if (hdr->length % CAPABILITY_CODE_PATHS_LIMIT_LEN) { + flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH, + "Paths-Limit: Received invalid length %d, non-multiple of %d", + hdr->length, CAPABILITY_CODE_PATHS_LIMIT_LEN); + return -1; + } + + if (!CHECK_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV)) { + flog_warn(EC_BGP_CAPABILITY_INVALID_DATA, + "Paths-Limit: Received Paths-Limit capability without Add-Path capability"); + return -1; + } + + SET_FLAG(peer->cap, PEER_CAP_PATHS_LIMIT_RCV); + + while (stream_get_getp(s) + CAPABILITY_CODE_PATHS_LIMIT_LEN <= end) { + afi_t afi; + safi_t safi; + iana_afi_t pkt_afi = stream_getw(s); + iana_safi_t pkt_safi = stream_getc(s); + uint16_t paths_limit = stream_getw(s); + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s OPEN has %s capability for afi/safi: %s/%s limit: %u", + peer->host, + lookup_msg(capcode_str, hdr->code, NULL), + iana_afi2str(pkt_afi), + iana_safi2str(pkt_safi), paths_limit); + + if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s Addr-family %s/%s(afi/safi) not supported. Ignore the Paths-Limit capability for this AFI/SAFI", + peer->host, iana_afi2str(pkt_afi), + iana_safi2str(pkt_safi)); + continue; + } else if (!peer->afc[afi][safi]) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s Addr-family %s/%s(afi/safi) not enabled. Ignore the Paths-Limit capability for this AFI/SAFI", + peer->host, iana_afi2str(pkt_afi), + iana_safi2str(pkt_safi)); + continue; + } + + SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_PATHS_LIMIT_AF_RCV); + peer->addpath_paths_limit[afi][safi].receive = paths_limit; } return 0; @@ -840,8 +877,6 @@ static int bgp_capability_hostname(struct peer *peer, size_t end = stream_get_getp(s) + hdr->length; uint8_t len; - SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV); - len = stream_getc(s); if (stream_get_getp(s) + len > end) { flog_warn( @@ -899,6 +934,8 @@ static int bgp_capability_hostname(struct peer *peer, peer->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST, str); } + SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV); + if (bgp_debug_neighbor_events(peer)) { zlog_debug("%s received hostname %s, domainname %s", peer->host, peer->hostname, peer->domainname); @@ -909,14 +946,16 @@ static int bgp_capability_hostname(struct peer *peer, static int bgp_capability_role(struct peer *peer, struct capability_header *hdr) { - SET_FLAG(peer->cap, PEER_CAP_ROLE_RCV); if (hdr->length != CAPABILITY_CODE_ROLE_LEN) { flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH, "Role: Received invalid length %d", hdr->length); return -1; } + uint8_t role = stream_getc(BGP_INPUT(peer)); + SET_FLAG(peer->cap, PEER_CAP_ROLE_RCV); + peer->remote_role = role; return 0; } @@ -929,8 +968,6 @@ static int bgp_capability_software_version(struct peer *peer, size_t end = stream_get_getp(s) + hdr->length; uint8_t len; - SET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_RCV); - len = stream_getc(s); if (stream_get_getp(s) + len > end) { flog_warn( @@ -940,8 +977,20 @@ static int bgp_capability_software_version(struct peer *peer, return -1; } - if (len) { + SET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_RCV); + + if (len > BGP_MAX_SOFT_VERSION) { + flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH, + "%s: Received Software Version, but the length is too big, truncating, from peer %s", + __func__, peer->host); + stream_get(str, s, BGP_MAX_SOFT_VERSION); + stream_forward_getp(s, len - BGP_MAX_SOFT_VERSION); + len = BGP_MAX_SOFT_VERSION; + } else if (len) { stream_get(str, s, len); + } + + if (len) { str[len] = '\0'; XFREE(MTYPE_BGP_SOFT_VERSION, peer->soft_version); @@ -983,7 +1032,7 @@ static int bgp_capability_parse(struct peer *peer, size_t length, if (stream_get_getp(s) + 2 > end) { zlog_info("%s Capability length error (< header)", peer->host); - bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send(peer->connection, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); return -1; } @@ -996,7 +1045,7 @@ static int bgp_capability_parse(struct peer *peer, size_t length, if (start + caphdr.length > end) { zlog_info("%s Capability length error (< length)", peer->host); - bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send(peer->connection, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); return -1; } @@ -1011,20 +1060,18 @@ static int bgp_capability_parse(struct peer *peer, size_t length, switch (caphdr.code) { case CAPABILITY_CODE_MP: case CAPABILITY_CODE_REFRESH: - case CAPABILITY_CODE_REFRESH_OLD: case CAPABILITY_CODE_ORF: - case CAPABILITY_CODE_ORF_OLD: case CAPABILITY_CODE_RESTART: case CAPABILITY_CODE_AS4: case CAPABILITY_CODE_ADDPATH: case CAPABILITY_CODE_DYNAMIC: - case CAPABILITY_CODE_DYNAMIC_OLD: case CAPABILITY_CODE_ENHE: case CAPABILITY_CODE_FQDN: case CAPABILITY_CODE_ENHANCED_RR: case CAPABILITY_CODE_EXT_MESSAGE: case CAPABILITY_CODE_ROLE: case CAPABILITY_CODE_SOFT_VERSION: + case CAPABILITY_CODE_PATHS_LIMIT: /* Check length. */ if (caphdr.length < cap_minsizes[caphdr.code]) { zlog_info( @@ -1034,7 +1081,8 @@ static int bgp_capability_parse(struct peer *peer, size_t length, NULL), caphdr.length, (unsigned)cap_minsizes[caphdr.code]); - bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send(peer->connection, + BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); return -1; } @@ -1047,10 +1095,12 @@ static int bgp_capability_parse(struct peer *peer, size_t length, NULL), caphdr.length, (unsigned)cap_modsizes[caphdr.code]); - bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send(peer->connection, + BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); return -1; } + break; /* we deliberately ignore unknown codes, see below */ default: break; @@ -1076,18 +1126,14 @@ static int bgp_capability_parse(struct peer *peer, size_t length, } } break; case CAPABILITY_CODE_ENHANCED_RR: - case CAPABILITY_CODE_REFRESH: - case CAPABILITY_CODE_REFRESH_OLD: { + case CAPABILITY_CODE_REFRESH: { /* BGP refresh capability */ if (caphdr.code == CAPABILITY_CODE_ENHANCED_RR) SET_FLAG(peer->cap, PEER_CAP_ENHANCED_RR_RCV); - else if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD) - SET_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV); else - SET_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV); + SET_FLAG(peer->cap, PEER_CAP_REFRESH_RCV); } break; case CAPABILITY_CODE_ORF: - case CAPABILITY_CODE_ORF_OLD: ret = bgp_capability_orf_entry(peer, &caphdr); break; case CAPABILITY_CODE_RESTART: @@ -1097,7 +1143,6 @@ static int bgp_capability_parse(struct peer *peer, size_t length, ret = bgp_capability_llgr(peer, &caphdr); break; case CAPABILITY_CODE_DYNAMIC: - case CAPABILITY_CODE_DYNAMIC_OLD: SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV); break; case CAPABILITY_CODE_AS4: @@ -1128,6 +1173,9 @@ static int bgp_capability_parse(struct peer *peer, size_t length, case CAPABILITY_CODE_SOFT_VERSION: ret = bgp_capability_software_version(peer, &caphdr); break; + case CAPABILITY_CODE_PATHS_LIMIT: + ret = bgp_capability_paths_limit(peer, &caphdr); + break; default: if (caphdr.code > 128) { /* We don't send Notification for unknown vendor @@ -1148,7 +1196,7 @@ static int bgp_capability_parse(struct peer *peer, size_t length, } if (ret < 0) { - bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send(peer->connection, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); return -1; } @@ -1196,7 +1244,7 @@ static bool bgp_role_violation(struct peer *peer) (local_role == ROLE_RS_SERVER && remote_role == ROLE_RS_CLIENT) || (local_role == ROLE_RS_CLIENT && remote_role == ROLE_RS_SERVER))) { - bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send(peer->connection, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_ROLE_MISMATCH); return true; } @@ -1204,7 +1252,7 @@ static bool bgp_role_violation(struct peer *peer) CHECK_FLAG(peer->flags, PEER_FLAG_ROLE_STRICT_MODE)) { const char *err_msg = "Strict mode. Please set the role on your side."; - bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send_with_data(peer->connection, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_ROLE_MISMATCH, (uint8_t *)err_msg, strlen(err_msg)); return true; @@ -1332,7 +1380,7 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length, */ if (STREAM_READABLE(s) < 1) { zlog_info("%s Option length error", peer->host); - bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send(peer->connection, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); return -1; } @@ -1345,7 +1393,8 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length, if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)) { if (STREAM_READABLE(s) < 2) { zlog_info("%s Option length error", peer->host); - bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send(peer->connection, + BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); return -1; } @@ -1354,7 +1403,8 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length, } else { if (STREAM_READABLE(s) < 1) { zlog_info("%s Option length error", peer->host); - bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send(peer->connection, + BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); return -1; } @@ -1366,7 +1416,7 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length, if (STREAM_READABLE(s) < opt_length) { zlog_info("%s Option length error (%d)", peer->host, opt_length); - bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send(peer->connection, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); return -1; } @@ -1385,7 +1435,7 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length, mp_capability, &error); break; default: - bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send(peer->connection, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_PARAM); ret = -1; break; @@ -1404,7 +1454,8 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length, if (CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) { /* If Unsupported Capability exists. */ if (error != error_data) { - bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send_with_data(peer->connection, + BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_CAPBL, error_data, error - error_data); @@ -1414,7 +1465,7 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length, /* Check local capability does not negotiated with remote peer. */ if (!strict_capability_same(peer)) { - bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send(peer->connection, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_CAPBL); return -1; } @@ -1453,12 +1504,14 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length, peer->host); if (error != error_data) - bgp_notify_send_with_data( - peer, BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNSUP_CAPBL, error_data, - error - error_data); + bgp_notify_send_with_data(peer->connection, + BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNSUP_CAPBL, + error_data, + error - error_data); else - bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + bgp_notify_send(peer->connection, + BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_CAPBL); return -1; } @@ -1498,9 +1551,7 @@ static void bgp_open_capability_orf(struct stream *s, struct peer *peer, /* Address Prefix ORF */ if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) || CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) { - stream_putc(s, (code == CAPABILITY_CODE_ORF - ? ORF_TYPE_PREFIX - : ORF_TYPE_PREFIX_OLD)); + stream_putc(s, ORF_TYPE_PREFIX); if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) @@ -1733,11 +1784,11 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer, * supporting RFC-5549 for * Link-Local peering only */ - if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE) - && peer->su.sa.sa_family == AF_INET6 - && afi == AFI_IP - && (safi == SAFI_UNICAST || safi == SAFI_MPLS_VPN - || safi == SAFI_LABELED_UNICAST)) { + if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE) && + peer->connection->su.sa.sa_family == AF_INET6 && + afi == AFI_IP && + (safi == SAFI_UNICAST || safi == SAFI_MPLS_VPN || + safi == SAFI_LABELED_UNICAST)) { /* RFC 5549 Extended Next Hop Encoding */ SET_FLAG(peer->cap, PEER_CAP_ENHE_ADV); @@ -1771,11 +1822,6 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer, stream_putc(s, BGP_OPEN_OPT_CAP); ext_opt_params ? stream_putw(s, CAPABILITY_CODE_REFRESH_LEN + 2) : stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2); - stream_putc(s, CAPABILITY_CODE_REFRESH_OLD); - stream_putc(s, CAPABILITY_CODE_REFRESH_LEN); - stream_putc(s, BGP_OPEN_OPT_CAP); - ext_opt_params ? stream_putw(s, CAPABILITY_CODE_REFRESH_LEN + 2) - : stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2); stream_putc(s, CAPABILITY_CODE_REFRESH); stream_putc(s, CAPABILITY_CODE_REFRESH_LEN); @@ -1891,6 +1937,31 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer, } } + /* Paths-Limit capability */ + SET_FLAG(peer->cap, PEER_CAP_PATHS_LIMIT_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + ext_opt_params ? stream_putw(s, (CAPABILITY_CODE_PATHS_LIMIT_LEN * + afi_safi_count) + + 2) + : stream_putc(s, (CAPABILITY_CODE_PATHS_LIMIT_LEN * + afi_safi_count) + + 2); + stream_putc(s, CAPABILITY_CODE_PATHS_LIMIT); + stream_putc(s, CAPABILITY_CODE_PATHS_LIMIT_LEN * afi_safi_count); + + FOREACH_AFI_SAFI (afi, safi) { + if (!peer->afc[afi][safi]) + continue; + + bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi); + + stream_putw(s, pkt_afi); + stream_putc(s, pkt_safi); + stream_putw(s, peer->addpath_paths_limit[afi][safi].send); + + SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_PATHS_LIMIT_AF_ADV); + } + /* ORF capability. */ FOREACH_AFI_SAFI (afi, safi) { if (CHECK_FLAG(peer->af_flags[afi][safi], @@ -1898,33 +1969,25 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer, || CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) { bgp_open_capability_orf(s, peer, afi, safi, - CAPABILITY_CODE_ORF_OLD, - ext_opt_params); - bgp_open_capability_orf(s, peer, afi, safi, CAPABILITY_CODE_ORF, ext_opt_params); } } /* Dynamic capability. */ - if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) { + if (peergroup_flag_check(peer, PEER_FLAG_DYNAMIC_CAPABILITY)) { SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV); stream_putc(s, BGP_OPEN_OPT_CAP); ext_opt_params ? stream_putw(s, CAPABILITY_CODE_DYNAMIC_LEN + 2) : stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2); - stream_putc(s, CAPABILITY_CODE_DYNAMIC_OLD); - stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN); - stream_putc(s, BGP_OPEN_OPT_CAP); - ext_opt_params - ? stream_putw(s, CAPABILITY_CODE_DYNAMIC_LEN + 2) - : stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2); stream_putc(s, CAPABILITY_CODE_DYNAMIC); stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN); } - /* Hostname capability */ - if (cmd_hostname_get()) { + /* FQDN capability */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_FQDN) + && cmd_hostname_get()) { SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV); stream_putc(s, BGP_OPEN_OPT_CAP); rcapp = stream_get_endp(s); /* Ptr to length placeholder */ @@ -1976,7 +2039,7 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer, * or disable its use, and that switch MUST be off by default. */ if (peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_SOFT_VERSION) || - peer->sort == BGP_PEER_IBGP) { + peer->sort == BGP_PEER_IBGP || peer->sub_sort == BGP_PEER_EBGP_OAD) { SET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_ADV); stream_putc(s, BGP_OPEN_OPT_CAP); rcapp = stream_get_endp(s); |
