summaryrefslogtreecommitdiff
path: root/bgpd/bgp_open.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_open.c')
-rw-r--r--bgpd/bgp_open.c353
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);