summaryrefslogtreecommitdiff
path: root/bgpd/bgp_packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_packet.c')
-rw-r--r--bgpd/bgp_packet.c137
1 files changed, 112 insertions, 25 deletions
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 2d1fc103bc..cc9b2c7bb4 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -1199,6 +1199,8 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
struct stream *s;
iana_afi_t pkt_afi = IANA_AFI_IPV4;
iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
+ unsigned long cap_len;
+ uint16_t len;
/* Convert AFI, SAFI to values for packet. */
bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
@@ -1209,7 +1211,41 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
bgp_packet_set_marker(s, BGP_MSG_CAPABILITY);
/* Encode MP_EXT capability. */
- if (capability_code == CAPABILITY_CODE_MP) {
+ switch (capability_code) {
+ case CAPABILITY_CODE_SOFT_VERSION:
+ SET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_ADV);
+ stream_putc(s, action);
+ stream_putc(s, CAPABILITY_CODE_SOFT_VERSION);
+ cap_len = stream_get_endp(s);
+ stream_putc(s, 0); /* Capability Length */
+
+ /* The Capability Length SHOULD be no greater than 64.
+ * This is the limit to allow other capabilities as much
+ * space as they require.
+ */
+ const char *soft_version = cmd_software_version_get();
+
+ len = strlen(soft_version);
+ if (len > BGP_MAX_SOFT_VERSION)
+ len = BGP_MAX_SOFT_VERSION;
+
+ stream_putc(s, len);
+ stream_put(s, soft_version, len);
+
+ /* Software Version capability Len. */
+ len = stream_get_endp(s) - cap_len - 1;
+ stream_putc_at(s, cap_len, len);
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP sending CAPABILITY has %s Software Version for afi/safi: %s/%s",
+ peer,
+ action == CAPABILITY_ACTION_SET
+ ? "Advertising"
+ : "Removing",
+ iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ break;
+ case CAPABILITY_CODE_MP:
stream_putc(s, action);
stream_putc(s, CAPABILITY_CODE_MP);
stream_putc(s, CAPABILITY_CODE_MP_LEN);
@@ -1224,6 +1260,22 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
action == CAPABILITY_ACTION_SET ? "Advertising"
: "Removing",
iana_afi2str(pkt_afi), iana_safi2str(pkt_safi));
+ break;
+ case CAPABILITY_CODE_REFRESH:
+ case CAPABILITY_CODE_ORF:
+ case CAPABILITY_CODE_RESTART:
+ case CAPABILITY_CODE_AS4:
+ case CAPABILITY_CODE_DYNAMIC:
+ case CAPABILITY_CODE_ADDPATH:
+ case CAPABILITY_CODE_ENHANCED_RR:
+ case CAPABILITY_CODE_LLGR:
+ case CAPABILITY_CODE_FQDN:
+ case CAPABILITY_CODE_ENHE:
+ case CAPABILITY_CODE_EXT_MESSAGE:
+ case CAPABILITY_CODE_ROLE:
+ break;
+ default:
+ break;
}
/* Set packet size. */
@@ -1735,11 +1787,14 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
|| peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
|| peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
|| peer->afc_nego[AFI_IP6][SAFI_ENCAP]) {
- if (IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_global)) {
-#if defined(HAVE_CUMULUS)
- zlog_warn("%s: No local IPv6 address, BGP routing may not work",
- peer->host);
-#endif
+ if (IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_global) &&
+ !bm->v6_with_v4_nexthops) {
+ flog_err(EC_BGP_SND_FAIL,
+"%s: No local IPv6 address, and zebra does not support V6 routing with v4 nexthops, BGP routing for V6 will not work",
+ peer->host);
+ bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+ return BGP_Stop;
}
}
peer->rtt = sockopt_tcp_rtt(peer->fd);
@@ -2698,6 +2753,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
afi_t afi;
iana_safi_t pkt_safi;
safi_t safi;
+ char soft_version[BGP_MAX_SOFT_VERSION + 1] = {};
end = pnt + length;
@@ -2728,14 +2784,6 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
"%s CAPABILITY has action: %d, code: %u, length %u",
peer->host, action, hdr->code, hdr->length);
- if (hdr->length < sizeof(struct capability_mp_data)) {
- zlog_info(
- "%pBP Capability structure is not properly filled out, expected at least %zu bytes but header length specified is %d",
- peer, sizeof(struct capability_mp_data),
- hdr->length);
- return BGP_Stop;
- }
-
/* Capability length check. */
if ((pnt + hdr->length + 3) > end) {
zlog_info("%s Capability length error", peer->host);
@@ -2744,20 +2792,42 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
return BGP_Stop;
}
- /* Fetch structure to the byte stream. */
- memcpy(&mpc, pnt + 3, sizeof(struct capability_mp_data));
- pnt += hdr->length + 3;
+ /* Ignore capability when override-capability is set. */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
+ continue;
+
+ switch (hdr->code) {
+ case CAPABILITY_CODE_SOFT_VERSION:
+ if (action == CAPABILITY_ACTION_SET) {
+ SET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_RCV);
+
+ memcpy(&soft_version, pnt + 3, hdr->length);
+ soft_version[hdr->length] = '\0';
+
+ XFREE(MTYPE_BGP_SOFT_VERSION,
+ peer->soft_version);
+ peer->soft_version =
+ XSTRDUP(MTYPE_BGP_SOFT_VERSION,
+ soft_version);
+ } else {
+ UNSET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_RCV);
+ XFREE(MTYPE_BGP_SOFT_VERSION,
+ peer->soft_version);
+ }
+ break;
+ case CAPABILITY_CODE_MP:
+ if (hdr->length < sizeof(struct capability_mp_data)) {
+ zlog_info("%pBP Capability structure is not properly filled out, expected at least %zu bytes but header length specified is %d",
+ peer,
+ sizeof(struct capability_mp_data),
+ hdr->length);
+ return BGP_Stop;
+ }
- /* We know MP Capability Code. */
- if (hdr->code == CAPABILITY_CODE_MP) {
+ memcpy(&mpc, pnt + 3, sizeof(struct capability_mp_data));
pkt_afi = ntohs(mpc.afi);
pkt_safi = mpc.safi;
- /* Ignore capability when override-capability is set. */
- if (CHECK_FLAG(peer->flags,
- PEER_FLAG_OVERRIDE_CAPABILITY))
- continue;
-
/* Convert AFI, SAFI to internal values. */
if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi,
&safi)) {
@@ -2797,12 +2867,29 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
else
return BGP_Stop;
}
- } else {
+ break;
+ case CAPABILITY_CODE_REFRESH:
+ case CAPABILITY_CODE_ORF:
+ case CAPABILITY_CODE_RESTART:
+ case CAPABILITY_CODE_AS4:
+ case CAPABILITY_CODE_DYNAMIC:
+ case CAPABILITY_CODE_ADDPATH:
+ case CAPABILITY_CODE_ENHANCED_RR:
+ case CAPABILITY_CODE_LLGR:
+ case CAPABILITY_CODE_FQDN:
+ case CAPABILITY_CODE_ENHE:
+ case CAPABILITY_CODE_EXT_MESSAGE:
+ case CAPABILITY_CODE_ROLE:
+ break;
+ default:
flog_warn(
EC_BGP_UNRECOGNIZED_CAPABILITY,
"%s unrecognized capability code: %d - ignored",
peer->host, hdr->code);
+ break;
}
+
+ pnt += hdr->length + 3;
}
/* No FSM action necessary */