diff options
Diffstat (limited to 'bgpd/bgp_open.c')
-rw-r--r-- | bgpd/bgp_open.c | 87 |
1 files changed, 54 insertions, 33 deletions
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index b030c45..6447586 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -340,15 +340,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"}, - {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) @@ -623,17 +622,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", @@ -663,10 +662,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", @@ -674,23 +671,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)) { @@ -709,13 +721,19 @@ 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; @@ -800,8 +818,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( @@ -859,6 +875,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); @@ -869,14 +887,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; } @@ -1020,6 +1040,7 @@ static int bgp_capability_parse(struct peer *peer, size_t length, BGP_NOTIFY_OPEN_MALFORMED_ATTR); return -1; } + break; /* we deliberately ignore unknown codes, see below */ default: break; @@ -1876,8 +1897,9 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer, 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 */ @@ -1929,8 +1951,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) || - CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SOFT_VERSION_CAPABILITY) || - 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); |