diff options
author | whitespace / reindent <invalid@invalid.invalid> | 2017-07-17 14:03:14 +0200 |
---|---|---|
committer | whitespace / reindent <invalid@invalid.invalid> | 2017-07-17 14:04:07 +0200 |
commit | d62a17aedeb0eebdba98238874bb13d62c48dbf9 (patch) | |
tree | 3b319b1d61c8b85b4d1f06adf8b844bb8a9b5107 /bgpd/bgp_open.c | |
parent | *: add indent control files (diff) | |
download | frr-d62a17aedeb0eebdba98238874bb13d62c48dbf9.tar.xz frr-d62a17aedeb0eebdba98238874bb13d62c48dbf9.zip |
*: reindentreindent-master-after
indent.py `git ls-files | pcregrep '\.[ch]$' | pcregrep -v '^(ldpd|babeld|nhrpd)/'`
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'bgpd/bgp_open.c')
-rw-r--r-- | bgpd/bgp_open.c | 2722 |
1 files changed, 1376 insertions, 1346 deletions
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index d6ed441df..b18a4b7c4 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -51,690 +51,711 @@ Next, if we send capability to the peer we want to set my capabilty inforation at each peer. */ -void -bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh) +void bgp_capability_vty_out(struct vty *vty, struct peer *peer, u_char use_json, + json_object *json_neigh) { - char *pnt; - char *end; - struct capability_mp_data mpc; - struct capability_header *hdr; - json_object *json_cap = NULL; - - if (use_json) - json_cap = json_object_new_object(); - - pnt = peer->notify.data; - end = pnt + peer->notify.length; - - while (pnt < end) - { - if (pnt + sizeof (struct capability_mp_data) + 2 > end) - return; - - hdr = (struct capability_header *)pnt; - if (pnt + hdr->length + 2 > end) - return; - - memcpy (&mpc, pnt + 2, sizeof(struct capability_mp_data)); - - if (hdr->code == CAPABILITY_CODE_MP) - { - afi_t afi; - safi_t safi; - - bgp_map_afi_safi_iana2int (ntohs(mpc.afi), mpc.safi, &afi, &safi); - if (use_json) - { - switch (afi) - { - case AFI_IP: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "IPv4"); - break; - case AFI_IP6: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "IPv6"); - break; - case AFI_L2VPN: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "L2VPN"); - break; - default: - json_object_int_add(json_cap, "capabilityErrorMultiProtocolAfiUnknown", ntohs (mpc.afi)); - break; - } - switch (safi) - { - case SAFI_UNICAST: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "unicast"); - break; - case SAFI_MULTICAST: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "multicast"); - break; - case SAFI_LABELED_UNICAST: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "labeled-unicast"); - break; - case SAFI_MPLS_VPN: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "MPLS-labeled VPN"); - break; - case SAFI_ENCAP: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "encap"); - break; - case SAFI_EVPN: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "EVPN"); - break; - default: - json_object_int_add(json_cap, "capabilityErrorMultiProtocolSafiUnknown", mpc.safi); - break; - } - } - else - { - vty_out (vty, " Capability error for: Multi protocol "); - switch (afi) - { - case AFI_IP: - vty_out (vty, "AFI IPv4, "); - break; - case AFI_IP6: - vty_out (vty, "AFI IPv6, "); - break; - case AFI_L2VPN: - vty_out (vty, "AFI L2VPN, "); - break; - default: - vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi)); - break; - } - switch (safi) - { - case SAFI_UNICAST: - vty_out (vty, "SAFI Unicast"); - break; - case SAFI_MULTICAST: - vty_out (vty, "SAFI Multicast"); - break; - case SAFI_LABELED_UNICAST: - vty_out (vty, "SAFI Labeled-unicast"); - break; - case SAFI_MPLS_VPN: - vty_out (vty, "SAFI MPLS-labeled VPN"); - break; - case SAFI_ENCAP: - vty_out (vty, "SAFI ENCAP"); - break; - case SAFI_EVPN: - vty_out (vty, "SAFI EVPN"); - break; - default: - vty_out (vty, "SAFI Unknown %d ", mpc.safi); - break; - } - vty_out (vty, "\n"); - } - } - else if (hdr->code >= 128) - { - if (use_json) - json_object_int_add(json_cap, "capabilityErrorVendorSpecificCapabilityCode", hdr->code); - else - vty_out (vty, " Capability error: vendor specific capability code %d", - hdr->code); - } - else - { - if (use_json) - json_object_int_add(json_cap, "capabilityErrorUnknownCapabilityCode", hdr->code); - else - vty_out (vty, " Capability error: unknown capability code %d", - hdr->code); - } - pnt += hdr->length + 2; - } - if (use_json) - json_object_object_add(json_neigh, "capabilityErrors", json_cap); + char *pnt; + char *end; + struct capability_mp_data mpc; + struct capability_header *hdr; + json_object *json_cap = NULL; + + if (use_json) + json_cap = json_object_new_object(); + + pnt = peer->notify.data; + end = pnt + peer->notify.length; + + while (pnt < end) { + if (pnt + sizeof(struct capability_mp_data) + 2 > end) + return; + + hdr = (struct capability_header *)pnt; + if (pnt + hdr->length + 2 > end) + return; + + memcpy(&mpc, pnt + 2, sizeof(struct capability_mp_data)); + + if (hdr->code == CAPABILITY_CODE_MP) { + afi_t afi; + safi_t safi; + + bgp_map_afi_safi_iana2int(ntohs(mpc.afi), mpc.safi, + &afi, &safi); + if (use_json) { + switch (afi) { + case AFI_IP: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolAfi", + "IPv4"); + break; + case AFI_IP6: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolAfi", + "IPv6"); + break; + case AFI_L2VPN: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolAfi", + "L2VPN"); + break; + default: + json_object_int_add( + json_cap, + "capabilityErrorMultiProtocolAfiUnknown", + ntohs(mpc.afi)); + break; + } + switch (safi) { + case SAFI_UNICAST: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolSafi", + "unicast"); + break; + case SAFI_MULTICAST: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolSafi", + "multicast"); + break; + case SAFI_LABELED_UNICAST: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolSafi", + "labeled-unicast"); + break; + case SAFI_MPLS_VPN: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolSafi", + "MPLS-labeled VPN"); + break; + case SAFI_ENCAP: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolSafi", + "encap"); + break; + case SAFI_EVPN: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolSafi", + "EVPN"); + break; + default: + json_object_int_add( + json_cap, + "capabilityErrorMultiProtocolSafiUnknown", + mpc.safi); + break; + } + } else { + vty_out(vty, + " Capability error for: Multi protocol "); + switch (afi) { + case AFI_IP: + vty_out(vty, "AFI IPv4, "); + break; + case AFI_IP6: + vty_out(vty, "AFI IPv6, "); + break; + case AFI_L2VPN: + vty_out(vty, "AFI L2VPN, "); + break; + default: + vty_out(vty, "AFI Unknown %d, ", + ntohs(mpc.afi)); + break; + } + switch (safi) { + case SAFI_UNICAST: + vty_out(vty, "SAFI Unicast"); + break; + case SAFI_MULTICAST: + vty_out(vty, "SAFI Multicast"); + break; + case SAFI_LABELED_UNICAST: + vty_out(vty, "SAFI Labeled-unicast"); + break; + case SAFI_MPLS_VPN: + vty_out(vty, "SAFI MPLS-labeled VPN"); + break; + case SAFI_ENCAP: + vty_out(vty, "SAFI ENCAP"); + break; + case SAFI_EVPN: + vty_out(vty, "SAFI EVPN"); + break; + default: + vty_out(vty, "SAFI Unknown %d ", + mpc.safi); + break; + } + vty_out(vty, "\n"); + } + } else if (hdr->code >= 128) { + if (use_json) + json_object_int_add( + json_cap, + "capabilityErrorVendorSpecificCapabilityCode", + hdr->code); + else + vty_out(vty, + " Capability error: vendor specific capability code %d", + hdr->code); + } else { + if (use_json) + json_object_int_add( + json_cap, + "capabilityErrorUnknownCapabilityCode", + hdr->code); + else + vty_out(vty, + " Capability error: unknown capability code %d", + hdr->code); + } + pnt += hdr->length + 2; + } + if (use_json) + json_object_object_add(json_neigh, "capabilityErrors", + json_cap); } -static void -bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc) +static void bgp_capability_mp_data(struct stream *s, + struct capability_mp_data *mpc) { - mpc->afi = stream_getw (s); - mpc->reserved = stream_getc (s); - mpc->safi = stream_getc (s); + mpc->afi = stream_getw(s); + mpc->reserved = stream_getc(s); + mpc->safi = stream_getc(s); } /* Set negotiated capability value. */ -static int -bgp_capability_mp (struct peer *peer, struct capability_header *hdr) +static int bgp_capability_mp(struct peer *peer, struct capability_header *hdr) { - struct capability_mp_data mpc; - struct stream *s = BGP_INPUT (peer); - afi_t afi; - safi_t safi; - - /* Verify length is 4 */ - if (hdr->length != 4) - { - zlog_warn("MP Cap: Received invalid length %d, non-multiple of 4", - hdr->length); - return -1; - } - - bgp_capability_mp_data (s, &mpc); - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u", - peer->host, mpc.afi, mpc.safi); - - /* Convert AFI, SAFI to internal values, check. */ - if (bgp_map_afi_safi_iana2int (mpc.afi, mpc.safi, &afi, &safi)) - return -1; - - /* Now safi remapped, and afi/safi are valid array indices */ - peer->afc_recv[afi][safi] = 1; - - if (peer->afc[afi][safi]) - peer->afc_nego[afi][safi] = 1; - else - return -1; - - return 0; + struct capability_mp_data mpc; + struct stream *s = BGP_INPUT(peer); + afi_t afi; + safi_t safi; + + /* Verify length is 4 */ + if (hdr->length != 4) { + zlog_warn( + "MP Cap: Received invalid length %d, non-multiple of 4", + hdr->length); + return -1; + } + + bgp_capability_mp_data(s, &mpc); + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s OPEN has MP_EXT CAP for afi/safi: %u/%u", + peer->host, mpc.afi, mpc.safi); + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int(mpc.afi, mpc.safi, &afi, &safi)) + return -1; + + /* Now safi remapped, and afi/safi are valid array indices */ + peer->afc_recv[afi][safi] = 1; + + if (peer->afc[afi][safi]) + peer->afc_nego[afi][safi] = 1; + else + return -1; + + return 0; } -static void -bgp_capability_orf_not_support (struct peer *peer, iana_afi_t afi, safi_t safi, - u_char type, u_char mode) +static void bgp_capability_orf_not_support(struct peer *peer, iana_afi_t afi, + safi_t safi, u_char type, + u_char mode) { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported", - peer->host, afi, safi, type, mode); + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Addr-family %d/%d has ORF type/mode %d/%d not supported", + peer->host, afi, safi, type, mode); } -static const struct message orf_type_str[] = -{ - { ORF_TYPE_PREFIX, "Prefixlist" }, - { ORF_TYPE_PREFIX_OLD, "Prefixlist (old)" }, - { 0 } -}; +static const struct message orf_type_str[] = { + {ORF_TYPE_PREFIX, "Prefixlist"}, + {ORF_TYPE_PREFIX_OLD, "Prefixlist (old)"}, + {0}}; -static const struct message orf_mode_str[] = -{ - { ORF_MODE_RECEIVE, "Receive" }, - { ORF_MODE_SEND, "Send" }, - { ORF_MODE_BOTH, "Both" }, - { 0 } -}; +static 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) +static int bgp_capability_orf_entry(struct peer *peer, + struct capability_header *hdr) { - struct stream *s = BGP_INPUT (peer); - struct capability_mp_data mpc; - u_char num; - iana_afi_t pkt_afi; - afi_t afi; - safi_t pkt_safi, safi; - u_char type; - u_char mode; - u_int16_t sm_cap = 0; /* capability send-mode receive */ - u_int16_t rm_cap = 0; /* capability receive-mode receive */ - int i; - - /* ORF Entry header */ - bgp_capability_mp_data (s, &mpc); - num = stream_getc (s); - pkt_afi = mpc.afi; - pkt_safi = mpc.safi; - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u", - peer->host, mpc.afi, mpc.safi); - - /* Convert AFI, SAFI to internal values, check. */ - if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) - { - zlog_info ("%s Addr-family %d/%d not supported." - " Ignoring the ORF capability", - peer->host, pkt_afi, pkt_safi); - return 0; - } - - mpc.afi = pkt_afi; - mpc.safi = safi; - - /* validate number field */ - if (CAPABILITY_CODE_ORF_LEN + (num * 2) > hdr->length) - { - 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_OPEN_MALFORMED_ATTR); - return -1; - } - - for (i = 0 ; i < num ; i++) - { - type = stream_getc(s); - mode = stream_getc(s); - - /* ORF Mode error check */ - switch (mode) - { - case ORF_MODE_BOTH: - case ORF_MODE_SEND: - case ORF_MODE_RECEIVE: - break; - default: - bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); - continue; + struct stream *s = BGP_INPUT(peer); + struct capability_mp_data mpc; + u_char num; + iana_afi_t pkt_afi; + afi_t afi; + safi_t pkt_safi, safi; + u_char type; + u_char mode; + u_int16_t sm_cap = 0; /* capability send-mode receive */ + u_int16_t rm_cap = 0; /* capability receive-mode receive */ + int i; + + /* ORF Entry header */ + bgp_capability_mp_data(s, &mpc); + num = stream_getc(s); + pkt_afi = mpc.afi; + pkt_safi = mpc.safi; + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s ORF Cap entry for afi/safi: %u/%u", peer->host, + mpc.afi, mpc.safi); + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { + zlog_info( + "%s Addr-family %d/%d not supported." + " Ignoring the ORF capability", + peer->host, pkt_afi, pkt_safi); + return 0; } - /* ORF Type and afi/safi error checks */ - /* capcode versus type */ - switch (hdr->code) - { - case CAPABILITY_CODE_ORF: - switch (type) - { - case ORF_TYPE_PREFIX: - break; - default: - bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); - continue; - } - break; - case CAPABILITY_CODE_ORF_OLD: - switch (type) - { - 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); - continue; - } - - /* AFI vs SAFI */ - if (!((afi == AFI_IP && safi == SAFI_UNICAST) - || (afi == AFI_IP && safi == SAFI_MULTICAST) - || (afi == AFI_IP6 && safi == SAFI_UNICAST))) - { - bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); - continue; - } - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s OPEN has %s ORF capability" - " as %s for afi/safi: %d/%d", - peer->host, lookup_msg(orf_type_str, type, NULL), - lookup_msg(orf_mode_str, mode, NULL), - pkt_afi, pkt_safi); - - 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); - continue; + + mpc.afi = pkt_afi; + mpc.safi = safi; + + /* validate number field */ + if (CAPABILITY_CODE_ORF_LEN + (num * 2) > hdr->length) { + 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_OPEN_MALFORMED_ATTR); + return -1; } - switch (mode) - { - case ORF_MODE_BOTH: - SET_FLAG (peer->af_cap[afi][safi], sm_cap); - SET_FLAG (peer->af_cap[afi][safi], rm_cap); - break; - case ORF_MODE_SEND: - SET_FLAG (peer->af_cap[afi][safi], sm_cap); - break; - case ORF_MODE_RECEIVE: - SET_FLAG (peer->af_cap[afi][safi], rm_cap); - break; + for (i = 0; i < num; i++) { + type = stream_getc(s); + mode = stream_getc(s); + + /* ORF Mode error check */ + switch (mode) { + case ORF_MODE_BOTH: + case ORF_MODE_SEND: + case ORF_MODE_RECEIVE: + break; + default: + bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi, + type, mode); + continue; + } + /* ORF Type and afi/safi error checks */ + /* capcode versus type */ + switch (hdr->code) { + case CAPABILITY_CODE_ORF: + switch (type) { + case ORF_TYPE_PREFIX: + break; + default: + bgp_capability_orf_not_support( + peer, pkt_afi, pkt_safi, type, mode); + continue; + } + break; + case CAPABILITY_CODE_ORF_OLD: + switch (type) { + 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); + continue; + } + + /* AFI vs SAFI */ + if (!((afi == AFI_IP && safi == SAFI_UNICAST) + || (afi == AFI_IP && safi == SAFI_MULTICAST) + || (afi == AFI_IP6 && safi == SAFI_UNICAST))) { + bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi, + type, mode); + continue; + } + + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s OPEN has %s ORF capability" + " as %s for afi/safi: %d/%d", + peer->host, + lookup_msg(orf_type_str, type, NULL), + lookup_msg(orf_mode_str, mode, NULL), pkt_afi, + pkt_safi); + + 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); + continue; + } + + switch (mode) { + case ORF_MODE_BOTH: + SET_FLAG(peer->af_cap[afi][safi], sm_cap); + SET_FLAG(peer->af_cap[afi][safi], rm_cap); + break; + case ORF_MODE_SEND: + SET_FLAG(peer->af_cap[afi][safi], sm_cap); + break; + case ORF_MODE_RECEIVE: + SET_FLAG(peer->af_cap[afi][safi], rm_cap); + break; + } } - } - return 0; + return 0; } -static int -bgp_capability_restart (struct peer *peer, struct capability_header *caphdr) +static int bgp_capability_restart(struct peer *peer, + struct capability_header *caphdr) { - struct stream *s = BGP_INPUT (peer); - u_int16_t restart_flag_time; - size_t end = stream_get_getp (s) + caphdr->length; - - /* Verify length is a multiple of 4 */ - if ((caphdr->length-2) % 4) - { - zlog_warn("Restart Cap: Received invalid length %d, non-multiple of 4", - caphdr->length); - return -1; - } - - SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV); - restart_flag_time = stream_getw(s); - if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT)) - SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV); - - UNSET_FLAG (restart_flag_time, 0xF000); - peer->v_gr_restart = restart_flag_time; - - if (bgp_debug_neighbor_events(peer)) - { - zlog_debug ("%s OPEN has Graceful Restart capability", peer->host); - zlog_debug ("%s Peer has%srestarted. Restart Time : %d", - peer->host, - CHECK_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV) ? " " - : " not ", - peer->v_gr_restart); - } - - while (stream_get_getp (s) + 4 <= end) - { - afi_t afi; - safi_t safi; - iana_afi_t pkt_afi = stream_getw (s); - safi_t pkt_safi = stream_getc (s); - u_char flag = stream_getc (s); - - /* Convert AFI, SAFI to internal values, check. */ - if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported." - " Ignore the Graceful Restart capability for this AFI/SAFI", - peer->host, pkt_afi, pkt_safi); - } - else if (!peer->afc[afi][safi]) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled." - " Ignore the Graceful Restart capability", - peer->host, pkt_afi, pkt_safi); - } - else - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Address family %s is%spreserved", peer->host, - afi_safi_print (afi, safi), - CHECK_FLAG (peer->af_cap[afi][safi], - PEER_CAP_RESTART_AF_PRESERVE_RCV) - ? " " : " not "); - - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV); - if (CHECK_FLAG (flag, RESTART_F_BIT)) - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV); - - } - } - return 0; + struct stream *s = BGP_INPUT(peer); + u_int16_t restart_flag_time; + size_t end = stream_get_getp(s) + caphdr->length; + + /* Verify length is a multiple of 4 */ + if ((caphdr->length - 2) % 4) { + zlog_warn( + "Restart Cap: Received invalid length %d, non-multiple of 4", + caphdr->length); + return -1; + } + + SET_FLAG(peer->cap, PEER_CAP_RESTART_RCV); + restart_flag_time = stream_getw(s); + if (CHECK_FLAG(restart_flag_time, RESTART_R_BIT)) + SET_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV); + + UNSET_FLAG(restart_flag_time, 0xF000); + peer->v_gr_restart = restart_flag_time; + + if (bgp_debug_neighbor_events(peer)) { + zlog_debug("%s OPEN has Graceful Restart capability", + peer->host); + zlog_debug("%s Peer has%srestarted. Restart Time : %d", + peer->host, + CHECK_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV) + ? " " + : " not ", + peer->v_gr_restart); + } + + while (stream_get_getp(s) + 4 <= end) { + afi_t afi; + safi_t safi; + iana_afi_t pkt_afi = stream_getw(s); + safi_t pkt_safi = stream_getc(s); + u_char flag = stream_getc(s); + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Addr-family %d/%d(afi/safi) not supported." + " Ignore the Graceful Restart capability for this AFI/SAFI", + peer->host, pkt_afi, pkt_safi); + } else if (!peer->afc[afi][safi]) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Addr-family %d/%d(afi/safi) not enabled." + " Ignore the Graceful Restart capability", + peer->host, pkt_afi, pkt_safi); + } else { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Address family %s is%spreserved", + peer->host, afi_safi_print(afi, safi), + CHECK_FLAG( + peer->af_cap[afi][safi], + PEER_CAP_RESTART_AF_PRESERVE_RCV) + ? " " + : " not "); + + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_RESTART_AF_RCV); + if (CHECK_FLAG(flag, RESTART_F_BIT)) + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_RESTART_AF_PRESERVE_RCV); + } + } + return 0; } /* Unlike other capability parsing routines, this one returns 0 on error */ -static as_t -bgp_capability_as4 (struct peer *peer, struct capability_header *hdr) +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) - { - zlog_err ("%s AS4 capability has incorrect data length %d", - peer->host, hdr->length); - return 0; - } - - as_t as4 = stream_getl (BGP_INPUT(peer)); - - if (BGP_DEBUG (as4, AS4)) - zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u", - peer->host, as4); - return as4; + SET_FLAG(peer->cap, PEER_CAP_AS4_RCV); + + if (hdr->length != CAPABILITY_CODE_AS4_LEN) { + zlog_err("%s AS4 capability has incorrect data length %d", + peer->host, hdr->length); + return 0; + } + + as_t as4 = stream_getl(BGP_INPUT(peer)); + + if (BGP_DEBUG(as4, AS4)) + zlog_debug( + "%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u", + peer->host, as4); + return as4; } -static int -bgp_capability_addpath (struct peer *peer, struct capability_header *hdr) +static int bgp_capability_addpath(struct peer *peer, + struct capability_header *hdr) { - 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) - { - zlog_warn("Add Path: Received invalid length %d, non-multiple of 4", - hdr->length); - return -1; - } - - while (stream_get_getp (s) + 4 <= end) - { - afi_t afi; - safi_t safi; - iana_afi_t pkt_afi = stream_getw (s); - safi_t pkt_safi = stream_getc (s); - u_char send_receive = stream_getc (s); - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s OPEN has AddPath CAP for afi/safi: %u/%u%s%s", - peer->host, pkt_afi, pkt_safi, - (send_receive & BGP_ADDPATH_RX) ? ", receive" : "", - (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)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported." - " Ignore the Addpath Attribute for this AFI/SAFI", - peer->host, pkt_afi, pkt_safi); - continue; - } - else if (!peer->afc[afi][safi]) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled." - " Ignore the AddPath capability for this AFI/SAFI", - peer->host, pkt_afi, pkt_safi); - continue; - } - - if (send_receive & BGP_ADDPATH_RX) - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_RCV); - - if (send_receive & BGP_ADDPATH_TX) - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV); - } - - return 0; + 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) { + zlog_warn( + "Add Path: Received invalid length %d, non-multiple of 4", + hdr->length); + return -1; + } + + while (stream_get_getp(s) + 4 <= end) { + afi_t afi; + safi_t safi; + iana_afi_t pkt_afi = stream_getw(s); + safi_t pkt_safi = stream_getc(s); + u_char send_receive = stream_getc(s); + + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s OPEN has AddPath CAP for afi/safi: %u/%u%s%s", + peer->host, pkt_afi, pkt_safi, + (send_receive & BGP_ADDPATH_RX) ? ", receive" + : "", + (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)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Addr-family %d/%d(afi/safi) not supported." + " Ignore the Addpath Attribute for this AFI/SAFI", + peer->host, pkt_afi, pkt_safi); + continue; + } else if (!peer->afc[afi][safi]) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Addr-family %d/%d(afi/safi) not enabled." + " Ignore the AddPath capability for this AFI/SAFI", + peer->host, pkt_afi, pkt_safi); + continue; + } + + if (send_receive & BGP_ADDPATH_RX) + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_RX_RCV); + + if (send_receive & BGP_ADDPATH_TX) + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_TX_RCV); + } + + return 0; } -static int -bgp_capability_enhe (struct peer *peer, struct capability_header *hdr) +static int bgp_capability_enhe(struct peer *peer, struct capability_header *hdr) { - struct stream *s = BGP_INPUT (peer); - size_t end = stream_get_getp (s) + hdr->length; - - /* Verify length is a multiple of 4 */ - if (hdr->length % 6) - { - zlog_warn("Extended NH: Received invalid length %d, non-multiple of 6", - hdr->length); - return -1; - } - - while (stream_get_getp (s) + 6 <= end) - { - iana_afi_t pkt_afi = stream_getw (s); - afi_t afi; - safi_t safi, pkt_safi = stream_getw (s); - iana_afi_t pkt_nh_afi = stream_getw (s); - afi_t nh_afi; - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Received with afi/safi/next-hop afi: %u/%u/%u", - peer->host, pkt_afi, pkt_safi, pkt_nh_afi); - - /* Convert AFI, SAFI to internal values, check. */ - if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported." - " Ignore the ENHE Attribute for this AFI/SAFI", - peer->host, pkt_afi, pkt_safi); - continue; - } - - /* RFC 5549 specifies use of this capability only for IPv4 AFI, with - * the Nexthop AFI being IPv6. A future spec may introduce other - * possibilities, so we ignore other values with a log. Also, only - * SAFI_UNICAST and SAFI_LABELED_UNICAST are currently supported (and expected). - */ - nh_afi = afi_iana2int (pkt_nh_afi); - - if (afi != AFI_IP || nh_afi != AFI_IP6 || !(safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) - { - zlog_warn ("%s Unexpected afi/safi/next-hop afi: %u/%u/%u " - "in Extended Next-hop capability, ignoring", - peer->host, pkt_afi, pkt_safi, pkt_nh_afi); - continue; - } - - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_RCV); - - if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_ADV)) - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_NEGO); - } - - SET_FLAG (peer->cap, PEER_CAP_ENHE_RCV); - - return 0; + struct stream *s = BGP_INPUT(peer); + size_t end = stream_get_getp(s) + hdr->length; + + /* Verify length is a multiple of 4 */ + if (hdr->length % 6) { + zlog_warn( + "Extended NH: Received invalid length %d, non-multiple of 6", + hdr->length); + return -1; + } + + while (stream_get_getp(s) + 6 <= end) { + iana_afi_t pkt_afi = stream_getw(s); + afi_t afi; + safi_t safi, pkt_safi = stream_getw(s); + iana_afi_t pkt_nh_afi = stream_getw(s); + afi_t nh_afi; + + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Received with afi/safi/next-hop afi: %u/%u/%u", + peer->host, pkt_afi, pkt_safi, pkt_nh_afi); + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Addr-family %d/%d(afi/safi) not supported." + " Ignore the ENHE Attribute for this AFI/SAFI", + peer->host, pkt_afi, pkt_safi); + continue; + } + + /* RFC 5549 specifies use of this capability only for IPv4 AFI, + * with + * the Nexthop AFI being IPv6. A future spec may introduce other + * possibilities, so we ignore other values with a log. Also, + * only + * SAFI_UNICAST and SAFI_LABELED_UNICAST are currently supported + * (and expected). + */ + nh_afi = afi_iana2int(pkt_nh_afi); + + if (afi != AFI_IP || nh_afi != AFI_IP6 + || !(safi == SAFI_UNICAST + || safi == SAFI_LABELED_UNICAST)) { + zlog_warn( + "%s Unexpected afi/safi/next-hop afi: %u/%u/%u " + "in Extended Next-hop capability, ignoring", + peer->host, pkt_afi, pkt_safi, pkt_nh_afi); + continue; + } + + SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_RCV); + + if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_ADV)) + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ENHE_AF_NEGO); + } + + SET_FLAG(peer->cap, PEER_CAP_ENHE_RCV); + + return 0; } -static int -bgp_capability_hostname (struct peer *peer, struct capability_header *hdr) +static int bgp_capability_hostname(struct peer *peer, + struct capability_header *hdr) { - struct stream *s = BGP_INPUT (peer); - char str[BGP_MAX_HOSTNAME+1]; - size_t end = stream_get_getp (s) + hdr->length; - u_char len; - - SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV); - - len = stream_getc(s); - if (stream_get_getp(s) + len > end) - { - zlog_warn("%s: Received malformed hostname capability from peer %s", - __FUNCTION__, peer->host); - return -1; - } - - if (len > BGP_MAX_HOSTNAME) - { - stream_get(str, s, BGP_MAX_HOSTNAME); - stream_forward_getp(s, len-BGP_MAX_HOSTNAME); - len = BGP_MAX_HOSTNAME; /* to set the '\0' below */ - } - else if (len) - stream_get(str, s, len); - - if (len) - { - str[len] = '\0'; - - if (peer->hostname != NULL) - { - XFREE(MTYPE_BGP_PEER_HOST, peer->hostname); - peer->hostname = NULL; - } - - if (peer->domainname != NULL) - { - XFREE(MTYPE_BGP_PEER_HOST, peer->domainname); - peer->domainname = NULL; - } - - peer->hostname = XSTRDUP(MTYPE_BGP_PEER_HOST, str); - } - - if (stream_get_getp(s) +1 > end) - { - zlog_warn("%s: Received invalid domain name len (hostname capability) from peer %s", - __FUNCTION__, peer->host); - return -1; - } - - len = stream_getc(s); - if (stream_get_getp(s) + len > end) - { - zlog_warn("%s: Received runt domain name (hostname capability) from peer %s", - __FUNCTION__, peer->host); - return -1; - } - - if (len > BGP_MAX_HOSTNAME) - { - stream_get(str, s, BGP_MAX_HOSTNAME); - stream_forward_getp(s, len-BGP_MAX_HOSTNAME); - len = BGP_MAX_HOSTNAME; /* to set the '\0' below */ - } - else if (len) - stream_get(str, s, len); - - if (len) - { - str[len] = '\0'; - peer->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST, str); - } - - if (bgp_debug_neighbor_events(peer)) - { - zlog_debug("%s received hostname %s, domainname %s", - peer->host, peer->hostname, peer->domainname); - } - - return 0; + struct stream *s = BGP_INPUT(peer); + char str[BGP_MAX_HOSTNAME + 1]; + size_t end = stream_get_getp(s) + hdr->length; + u_char len; + + SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV); + + len = stream_getc(s); + if (stream_get_getp(s) + len > end) { + zlog_warn( + "%s: Received malformed hostname capability from peer %s", + __FUNCTION__, peer->host); + return -1; + } + + if (len > BGP_MAX_HOSTNAME) { + stream_get(str, s, BGP_MAX_HOSTNAME); + stream_forward_getp(s, len - BGP_MAX_HOSTNAME); + len = BGP_MAX_HOSTNAME; /* to set the '\0' below */ + } else if (len) + stream_get(str, s, len); + + if (len) { + str[len] = '\0'; + + if (peer->hostname != NULL) { + XFREE(MTYPE_BGP_PEER_HOST, peer->hostname); + peer->hostname = NULL; + } + + if (peer->domainname != NULL) { + XFREE(MTYPE_BGP_PEER_HOST, peer->domainname); + peer->domainname = NULL; + } + + peer->hostname = XSTRDUP(MTYPE_BGP_PEER_HOST, str); + } + + if (stream_get_getp(s) + 1 > end) { + zlog_warn( + "%s: Received invalid domain name len (hostname capability) from peer %s", + __FUNCTION__, peer->host); + return -1; + } + + len = stream_getc(s); + if (stream_get_getp(s) + len > end) { + zlog_warn( + "%s: Received runt domain name (hostname capability) from peer %s", + __FUNCTION__, peer->host); + return -1; + } + + if (len > BGP_MAX_HOSTNAME) { + stream_get(str, s, BGP_MAX_HOSTNAME); + stream_forward_getp(s, len - BGP_MAX_HOSTNAME); + len = BGP_MAX_HOSTNAME; /* to set the '\0' below */ + } else if (len) + stream_get(str, s, len); + + if (len) { + str[len] = '\0'; + peer->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST, str); + } + + if (bgp_debug_neighbor_events(peer)) { + zlog_debug("%s received hostname %s, domainname %s", peer->host, + peer->hostname, peer->domainname); + } + + return 0; } - 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" }, - { 0 } -}; +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"}, + {0}}; /* Minimum sizes for length field of each cap (so not inc. the header) */ -static const size_t cap_minsizes[] = -{ - [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN, - [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN, - [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN, - [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN, - [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, +static const size_t cap_minsizes[] = { + [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN, + [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN, + [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN, + [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN, + [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, }; /* value the capability must be a multiple of. @@ -742,20 +763,19 @@ static const size_t cap_minsizes[] = * Other capabilities whose data doesn't fall on convenient boundaries for this * table should be set to 1. */ -static const size_t cap_modsizes[] = -{ - [CAPABILITY_CODE_MP] = 4, - [CAPABILITY_CODE_REFRESH] = 1, - [CAPABILITY_CODE_ORF] = 1, - [CAPABILITY_CODE_RESTART] = 1, - [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, +static const size_t cap_modsizes[] = { + [CAPABILITY_CODE_MP] = 4, + [CAPABILITY_CODE_REFRESH] = 1, + [CAPABILITY_CODE_ORF] = 1, + [CAPABILITY_CODE_RESTART] = 1, + [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, }; /** @@ -765,281 +785,276 @@ static const size_t cap_modsizes[] = * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol * capabilities were encountered. */ -static int -bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability, - u_char **error) +static int bgp_capability_parse(struct peer *peer, size_t length, + int *mp_capability, u_char **error) { - int ret; - struct stream *s = BGP_INPUT (peer); - size_t end = stream_get_getp (s) + length; - - assert (STREAM_READABLE (s) >= length); - - while (stream_get_getp (s) < end) - { - size_t start; - u_char *sp = stream_pnt (s); - struct capability_header caphdr; - - ret = 0; - /* We need at least capability code and capability 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_OPEN_MALFORMED_ATTR); - return -1; - } - - caphdr.code = stream_getc (s); - caphdr.length = stream_getc (s); - start = stream_get_getp (s); - - /* Capability length check sanity check. */ - if (start + caphdr.length > end) - { - zlog_info ("%s Capability length error (< length)", peer->host); - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; + int ret; + struct stream *s = BGP_INPUT(peer); + size_t end = stream_get_getp(s) + length; + + assert(STREAM_READABLE(s) >= length); + + while (stream_get_getp(s) < end) { + size_t start; + u_char *sp = stream_pnt(s); + struct capability_header caphdr; + + ret = 0; + /* We need at least capability code and capability 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_OPEN_MALFORMED_ATTR); + return -1; + } + + caphdr.code = stream_getc(s); + caphdr.length = stream_getc(s); + start = stream_get_getp(s); + + /* Capability length check sanity check. */ + if (start + caphdr.length > end) { + zlog_info("%s Capability length error (< length)", + peer->host); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s OPEN has %s capability (%u), length %u", + peer->host, + lookup_msg(capcode_str, caphdr.code, NULL), + caphdr.code, caphdr.length); + + /* Length sanity check, type-specific, for known capabilities */ + 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: + /* Check length. */ + if (caphdr.length < cap_minsizes[caphdr.code]) { + zlog_info( + "%s %s Capability length error: got %u," + " expected at least %u", + peer->host, + lookup_msg(capcode_str, caphdr.code, + NULL), + caphdr.length, + (unsigned)cap_minsizes[caphdr.code]); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } + if (caphdr.length + && caphdr.length % cap_modsizes[caphdr.code] != 0) { + zlog_info( + "%s %s Capability length error: got %u," + " expected a multiple of %u", + peer->host, + lookup_msg(capcode_str, caphdr.code, + NULL), + caphdr.length, + (unsigned)cap_modsizes[caphdr.code]); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } + /* we deliberately ignore unknown codes, see below */ + default: + break; + } + + switch (caphdr.code) { + case CAPABILITY_CODE_MP: { + *mp_capability = 1; + + /* Ignore capability when override-capability is set. */ + if (!CHECK_FLAG(peer->flags, + PEER_FLAG_OVERRIDE_CAPABILITY)) { + /* Set negotiated value. */ + ret = bgp_capability_mp(peer, &caphdr); + + /* Unsupported Capability. */ + if (ret < 0) { + /* Store return data. */ + memcpy(*error, sp, caphdr.length + 2); + *error += caphdr.length + 2; + } + ret = 0; /* Don't return error for this */ + } + } break; + case CAPABILITY_CODE_REFRESH: + case CAPABILITY_CODE_REFRESH_OLD: { + /* BGP refresh capability */ + 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); + } break; + case CAPABILITY_CODE_ORF: + case CAPABILITY_CODE_ORF_OLD: + ret = bgp_capability_orf_entry(peer, &caphdr); + break; + case CAPABILITY_CODE_RESTART: + ret = bgp_capability_restart(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: + /* Already handled as a special-case parsing of the + * capabilities + * at the beginning of OPEN processing. So we care not a + * jot + * for the value really, only error case. + */ + if (!bgp_capability_as4(peer, &caphdr)) + ret = -1; + break; + case CAPABILITY_CODE_ADDPATH: + ret = bgp_capability_addpath(peer, &caphdr); + break; + case CAPABILITY_CODE_ENHE: + ret = bgp_capability_enhe(peer, &caphdr); + break; + case CAPABILITY_CODE_FQDN: + ret = bgp_capability_hostname(peer, &caphdr); + break; + default: + if (caphdr.code > 128) { + /* We don't send Notification for unknown vendor + specific + capabilities. It seems reasonable for now... + */ + zlog_warn("%s Vendor specific capability %d", + peer->host, caphdr.code); + } else { + zlog_warn( + "%s unrecognized capability code: %d - ignored", + peer->host, caphdr.code); + memcpy(*error, sp, caphdr.length + 2); + *error += caphdr.length + 2; + } + } + + if (ret < 0) { + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } + if (stream_get_getp(s) != (start + caphdr.length)) { + if (stream_get_getp(s) > (start + caphdr.length)) + zlog_warn( + "%s Cap-parser for %s read past cap-length, %u!", + peer->host, + lookup_msg(capcode_str, caphdr.code, + NULL), + caphdr.length); + stream_set_getp(s, start + caphdr.length); + } } - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s OPEN has %s capability (%u), length %u", - peer->host, - lookup_msg(capcode_str, caphdr.code, NULL), - caphdr.code, caphdr.length); - - /* Length sanity check, type-specific, for known capabilities */ - 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: - /* Check length. */ - if (caphdr.length < cap_minsizes[caphdr.code]) - { - zlog_info ("%s %s Capability length error: got %u," - " expected at least %u", - peer->host, - lookup_msg(capcode_str, caphdr.code, NULL), - caphdr.length, - (unsigned) cap_minsizes[caphdr.code]); - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; - } - if (caphdr.length - && caphdr.length % cap_modsizes[caphdr.code] != 0) - { - zlog_info ("%s %s Capability length error: got %u," - " expected a multiple of %u", - peer->host, - lookup_msg(capcode_str, caphdr.code, NULL), - caphdr.length, - (unsigned) cap_modsizes[caphdr.code]); - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; - } - /* we deliberately ignore unknown codes, see below */ - default: - break; - } - - switch (caphdr.code) - { - case CAPABILITY_CODE_MP: - { - *mp_capability = 1; - - /* Ignore capability when override-capability is set. */ - if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) - { - /* Set negotiated value. */ - ret = bgp_capability_mp (peer, &caphdr); - - /* Unsupported Capability. */ - if (ret < 0) - { - /* Store return data. */ - memcpy (*error, sp, caphdr.length + 2); - *error += caphdr.length + 2; - } - ret = 0; /* Don't return error for this */ - } - } - break; - case CAPABILITY_CODE_REFRESH: - case CAPABILITY_CODE_REFRESH_OLD: - { - /* BGP refresh capability */ - 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); - } - break; - case CAPABILITY_CODE_ORF: - case CAPABILITY_CODE_ORF_OLD: - ret = bgp_capability_orf_entry (peer, &caphdr); - break; - case CAPABILITY_CODE_RESTART: - ret = bgp_capability_restart (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: - /* Already handled as a special-case parsing of the capabilities - * at the beginning of OPEN processing. So we care not a jot - * for the value really, only error case. - */ - if (!bgp_capability_as4 (peer, &caphdr)) - ret = -1; - break; - case CAPABILITY_CODE_ADDPATH: - ret = bgp_capability_addpath (peer, &caphdr); - break; - case CAPABILITY_CODE_ENHE: - ret = bgp_capability_enhe (peer, &caphdr); - break; - case CAPABILITY_CODE_FQDN: - ret = bgp_capability_hostname (peer, &caphdr); - break; - default: - if (caphdr.code > 128) - { - /* We don't send Notification for unknown vendor specific - capabilities. It seems reasonable for now... */ - zlog_warn ("%s Vendor specific capability %d", - peer->host, caphdr.code); - } - else - { - zlog_warn ("%s unrecognized capability code: %d - ignored", - peer->host, caphdr.code); - memcpy (*error, sp, caphdr.length + 2); - *error += caphdr.length + 2; - } - } - - if (ret < 0) - { - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; - } - if (stream_get_getp(s) != (start + caphdr.length)) - { - if (stream_get_getp(s) > (start + caphdr.length)) - zlog_warn ("%s Cap-parser for %s read past cap-length, %u!", - peer->host, lookup_msg(capcode_str, caphdr.code, NULL), - caphdr.length); - stream_set_getp (s, start + caphdr.length); - } - } - return 0; + return 0; } -static int -bgp_auth_parse (struct peer *peer, size_t length) +static int bgp_auth_parse(struct peer *peer, size_t length) { - bgp_notify_send (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_AUTH_FAILURE); - return -1; + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_AUTH_FAILURE); + return -1; } -static int -strict_capability_same (struct peer *peer) +static int strict_capability_same(struct peer *peer) { - int i, j; + int i, j; - for (i = AFI_IP; i < AFI_MAX; i++) - for (j = SAFI_UNICAST; j < SAFI_MAX; j++) - if (peer->afc[i][j] != peer->afc_nego[i][j]) - return 0; - return 1; + for (i = AFI_IP; i < AFI_MAX; i++) + for (j = SAFI_UNICAST; j < SAFI_MAX; j++) + if (peer->afc[i][j] != peer->afc_nego[i][j]) + return 0; + return 1; } /* peek into option, stores ASN to *as4 if the AS4 capability was found. * Returns 0 if no as4 found, as4cap value otherwise. */ -as_t -peek_for_as4_capability (struct peer *peer, u_char length) +as_t peek_for_as4_capability(struct peer *peer, u_char length) { - struct stream *s = BGP_INPUT (peer); - size_t orig_getp = stream_get_getp (s); - size_t end = orig_getp + length; - as_t as4 = 0; - - if (BGP_DEBUG (as4, AS4)) - zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u," - " peeking for as4", - peer->host, length); - /* the error cases we DONT handle, we ONLY try to read as4 out of - * correctly formatted options. - */ - while (stream_get_getp(s) < end) - { - u_char opt_type; - u_char opt_length; - - /* Check the length. */ - if (stream_get_getp (s) + 2 > end) - goto end; - - /* Fetch option type and length. */ - opt_type = stream_getc (s); - opt_length = stream_getc (s); - - /* Option length check. */ - if (stream_get_getp (s) + opt_length > end) - goto end; - - if (opt_type == BGP_OPEN_OPT_CAP) - { - unsigned long capd_start = stream_get_getp (s); - unsigned long capd_end = capd_start + opt_length; - - assert (capd_end <= end); - - while (stream_get_getp (s) < capd_end) - { - struct capability_header hdr; - - if (stream_get_getp (s) + 2 > capd_end) - goto end; - - hdr.code = stream_getc (s); - hdr.length = stream_getc (s); - - if ((stream_get_getp(s) + hdr.length) > capd_end) - goto end; - - if (hdr.code == CAPABILITY_CODE_AS4) - { - if (BGP_DEBUG (as4, AS4)) - zlog_info ("[AS4] found AS4 capability, about to parse"); - as4 = bgp_capability_as4 (peer, &hdr); - - goto end; - } - stream_forward_getp (s, hdr.length); - } + struct stream *s = BGP_INPUT(peer); + size_t orig_getp = stream_get_getp(s); + size_t end = orig_getp + length; + as_t as4 = 0; + + if (BGP_DEBUG(as4, AS4)) + zlog_info( + "%s [AS4] rcv OPEN w/ OPTION parameter len: %u," + " peeking for as4", + peer->host, length); + /* the error cases we DONT handle, we ONLY try to read as4 out of + * correctly formatted options. + */ + while (stream_get_getp(s) < end) { + u_char opt_type; + u_char opt_length; + + /* Check the length. */ + if (stream_get_getp(s) + 2 > end) + goto end; + + /* Fetch option type and length. */ + opt_type = stream_getc(s); + opt_length = stream_getc(s); + + /* Option length check. */ + if (stream_get_getp(s) + opt_length > end) + goto end; + + if (opt_type == BGP_OPEN_OPT_CAP) { + unsigned long capd_start = stream_get_getp(s); + unsigned long capd_end = capd_start + opt_length; + + assert(capd_end <= end); + + while (stream_get_getp(s) < capd_end) { + struct capability_header hdr; + + if (stream_get_getp(s) + 2 > capd_end) + goto end; + + hdr.code = stream_getc(s); + hdr.length = stream_getc(s); + + if ((stream_get_getp(s) + hdr.length) + > capd_end) + goto end; + + if (hdr.code == CAPABILITY_CODE_AS4) { + if (BGP_DEBUG(as4, AS4)) + zlog_info( + "[AS4] found AS4 capability, about to parse"); + as4 = bgp_capability_as4(peer, &hdr); + + goto end; + } + stream_forward_getp(s, hdr.length); + } + } } - } end: - stream_set_getp (s, orig_getp); - return as4; + stream_set_getp(s, orig_getp); + return as4; } /** @@ -1047,461 +1062,476 @@ end: * * @param[out] mp_capability @see bgp_capability_parse() for semantics. */ -int -bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability) +int bgp_open_option_parse(struct peer *peer, u_char length, int *mp_capability) { - int ret = 0; - u_char *error; - u_char error_data[BGP_MAX_PACKET_SIZE]; - struct stream *s = BGP_INPUT(peer); - size_t end = stream_get_getp (s) + length; - - error = error_data; - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u", - peer->host, length); - - while (stream_get_getp(s) < end) - { - u_char opt_type; - u_char opt_length; - - /* Must have at least an OPEN option header */ - if (STREAM_READABLE(s) < 2) - { - zlog_info ("%s Option length error", peer->host); - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; - } - - /* Fetch option type and length. */ - opt_type = stream_getc (s); - opt_length = stream_getc (s); - - /* Option length check. */ - if (STREAM_READABLE (s) < opt_length) - { - zlog_info ("%s Option length error", peer->host); - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; + int ret = 0; + u_char *error; + u_char error_data[BGP_MAX_PACKET_SIZE]; + struct stream *s = BGP_INPUT(peer); + size_t end = stream_get_getp(s) + length; + + error = error_data; + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s rcv OPEN w/ OPTION parameter len: %u", + peer->host, length); + + while (stream_get_getp(s) < end) { + u_char opt_type; + u_char opt_length; + + /* Must have at least an OPEN option header */ + if (STREAM_READABLE(s) < 2) { + zlog_info("%s Option length error", peer->host); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } + + /* Fetch option type and length. */ + opt_type = stream_getc(s); + opt_length = stream_getc(s); + + /* Option length check. */ + if (STREAM_READABLE(s) < opt_length) { + zlog_info("%s Option length error", peer->host); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } + + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s rcvd OPEN w/ optional parameter type %u (%s) len %u", + peer->host, opt_type, + opt_type == BGP_OPEN_OPT_AUTH + ? "Authentication" + : opt_type == BGP_OPEN_OPT_CAP + ? "Capability" + : "Unknown", + opt_length); + + switch (opt_type) { + case BGP_OPEN_OPT_AUTH: + ret = bgp_auth_parse(peer, opt_length); + break; + case BGP_OPEN_OPT_CAP: + ret = bgp_capability_parse(peer, opt_length, + mp_capability, &error); + break; + default: + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNSUP_PARAM); + ret = -1; + break; + } + + /* Parse error. To accumulate all unsupported capability codes, + bgp_capability_parse does not return -1 when encounter + unsupported capability code. To detect that, please check + error and erro_data pointer, like below. */ + if (ret < 0) + return -1; } - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u", - peer->host, opt_type, - opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" : - opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown", - opt_length); - - switch (opt_type) - { - case BGP_OPEN_OPT_AUTH: - ret = bgp_auth_parse (peer, opt_length); - break; - case BGP_OPEN_OPT_CAP: - ret = bgp_capability_parse (peer, opt_length, mp_capability, &error); - break; - default: - bgp_notify_send (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNSUP_PARAM); - ret = -1; - break; + /* All OPEN option is parsed. Check capability when strict compare + flag is enabled.*/ + 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_OPEN_UNSUP_CAPBL, + error_data, + error - error_data); + return -1; + } + + /* Check local capability does not negotiated with remote + peer. */ + if (!strict_capability_same(peer)) { + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNSUP_CAPBL); + return -1; + } } - /* Parse error. To accumulate all unsupported capability codes, - bgp_capability_parse does not return -1 when encounter - unsupported capability code. To detect that, please check - error and erro_data pointer, like below. */ - if (ret < 0) - return -1; - } - - /* All OPEN option is parsed. Check capability when strict compare - flag is enabled.*/ - 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_OPEN_UNSUP_CAPBL, - error_data, error - error_data); - return -1; + /* Check there are no common AFI/SAFIs and send Unsupported Capability + error. */ + if (*mp_capability + && !CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) { + if (!peer->afc_nego[AFI_IP][SAFI_UNICAST] + && !peer->afc_nego[AFI_IP][SAFI_MULTICAST] + && !peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST] + && !peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] + && !peer->afc_nego[AFI_IP][SAFI_ENCAP] + && !peer->afc_nego[AFI_IP6][SAFI_UNICAST] + && !peer->afc_nego[AFI_IP6][SAFI_MULTICAST] + && !peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] + && !peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] + && !peer->afc_nego[AFI_IP6][SAFI_ENCAP] + && !peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) { + zlog_err( + "%s [Error] Configured AFI/SAFIs do not " + "overlap with received MP capabilities", + 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); + else + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNSUP_CAPBL); + return -1; + } } - - /* Check local capability does not negotiated with remote - peer. */ - if (! strict_capability_same (peer)) - { - bgp_notify_send (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNSUP_CAPBL); - return -1; - } - } - - /* Check there are no common AFI/SAFIs and send Unsupported Capability - error. */ - if (*mp_capability && - ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) - { - if (! peer->afc_nego[AFI_IP][SAFI_UNICAST] - && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST] - && ! peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST] - && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] - && ! peer->afc_nego[AFI_IP][SAFI_ENCAP] - && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST] - && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST] - && ! peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] - && ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] - && ! peer->afc_nego[AFI_IP6][SAFI_ENCAP] - && ! peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) - { - zlog_err ("%s [Error] Configured AFI/SAFIs do not " - "overlap with received MP capabilities", - 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); - else - bgp_notify_send (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNSUP_CAPBL); - return -1; - } - } - return 0; + return 0; } -static void -bgp_open_capability_orf (struct stream *s, struct peer *peer, - afi_t afi, safi_t safi, u_char code) +static void bgp_open_capability_orf(struct stream *s, struct peer *peer, + afi_t afi, safi_t safi, u_char code) { - u_char cap_len; - u_char orf_len; - unsigned long capp; - unsigned long orfp; - unsigned long numberp; - int number_of_orfs = 0; - iana_afi_t pkt_afi; - safi_t pkt_safi; - - /* Convert AFI, SAFI to values for packet. */ - bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); - - stream_putc (s, BGP_OPEN_OPT_CAP); - capp = stream_get_endp (s); /* Set Capability Len Pointer */ - stream_putc (s, 0); /* Capability Length */ - stream_putc (s, code); /* Capability Code */ - orfp = stream_get_endp (s); /* Set ORF Len Pointer */ - stream_putc (s, 0); /* ORF Length */ - stream_putw (s, pkt_afi); - stream_putc (s, 0); - stream_putc (s, pkt_safi); - numberp = stream_get_endp (s); /* Set Number Pointer */ - stream_putc (s, 0); /* Number of ORFs */ - - /* 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)); - - 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)) - { - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV); - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV); - stream_putc (s, ORF_MODE_BOTH); - } - else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)) - { - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV); - stream_putc (s, ORF_MODE_SEND); - } - else - { - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV); - stream_putc (s, ORF_MODE_RECEIVE); + u_char cap_len; + u_char orf_len; + unsigned long capp; + unsigned long orfp; + unsigned long numberp; + int number_of_orfs = 0; + iana_afi_t pkt_afi; + safi_t pkt_safi; + + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi); + + stream_putc(s, BGP_OPEN_OPT_CAP); + capp = stream_get_endp(s); /* Set Capability Len Pointer */ + stream_putc(s, 0); /* Capability Length */ + stream_putc(s, code); /* Capability Code */ + orfp = stream_get_endp(s); /* Set ORF Len Pointer */ + stream_putc(s, 0); /* ORF Length */ + stream_putw(s, pkt_afi); + stream_putc(s, 0); + stream_putc(s, pkt_safi); + numberp = stream_get_endp(s); /* Set Number Pointer */ + stream_putc(s, 0); /* Number of ORFs */ + + /* 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)); + + 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)) { + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_ADV); + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_ADV); + stream_putc(s, ORF_MODE_BOTH); + } else if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ORF_PREFIX_SM)) { + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_ADV); + stream_putc(s, ORF_MODE_SEND); + } else { + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_ADV); + stream_putc(s, ORF_MODE_RECEIVE); + } + number_of_orfs++; } - number_of_orfs++; - } - /* Total Number of ORFs. */ - stream_putc_at (s, numberp, number_of_orfs); + /* Total Number of ORFs. */ + stream_putc_at(s, numberp, number_of_orfs); - /* Total ORF Len. */ - orf_len = stream_get_endp (s) - orfp - 1; - stream_putc_at (s, orfp, orf_len); + /* Total ORF Len. */ + orf_len = stream_get_endp(s) - orfp - 1; + stream_putc_at(s, orfp, orf_len); - /* Total Capability Len. */ - cap_len = stream_get_endp (s) - capp - 1; - stream_putc_at (s, capp, cap_len); + /* Total Capability Len. */ + cap_len = stream_get_endp(s) - capp - 1; + stream_putc_at(s, capp, cap_len); } /* Fill in capability open option to the packet. */ -void -bgp_open_capability (struct stream *s, struct peer *peer) +void bgp_open_capability(struct stream *s, struct peer *peer) { - u_char len; - unsigned long cp, capp, rcapp; - iana_afi_t pkt_afi; - afi_t afi; - safi_t safi, pkt_safi; - as_t local_as; - u_int32_t restart_time; - u_char afi_safi_count = 0; - struct utsname names; - int adv_addpath_tx = 0; - - /* Remember current pointer for Opt Parm Len. */ - cp = stream_get_endp (s); - - /* Opt Parm Len. */ - stream_putc (s, 0); - - /* Do not send capability. */ - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN) - || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY)) - return; - - /* MP capability for configured AFI, SAFI */ - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - if (peer->afc[afi][safi]) - { - /* Convert AFI, SAFI to values for packet. */ - bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); - - peer->afc_adv[afi][safi] = 1; - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); - stream_putc (s, CAPABILITY_CODE_MP); - stream_putc (s, CAPABILITY_CODE_MP_LEN); - stream_putw (s, pkt_afi); - stream_putc (s, 0); - stream_putc (s, pkt_safi); - - /* Extended nexthop capability - currently supporting RFC-5549 for - * Link-Local peering only - */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE) && - peer->su.sa.sa_family == AF_INET6 && - IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr) && - afi == AFI_IP && - (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) - { - /* RFC 5549 Extended Next Hop Encoding */ - SET_FLAG (peer->cap, PEER_CAP_ENHE_ADV); - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_ENHE_LEN + 2); - stream_putc (s, CAPABILITY_CODE_ENHE); - stream_putc (s, CAPABILITY_CODE_ENHE_LEN); - - SET_FLAG (peer->af_cap[AFI_IP][safi], PEER_CAP_ENHE_AF_ADV); - stream_putw (s, pkt_afi); - stream_putw (s, pkt_safi); - stream_putw (s, afi_int2iana(AFI_IP6)); - - if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_RCV)) - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_NEGO); - } - } - } - - /* Route refresh. */ - SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV); - stream_putc (s, BGP_OPEN_OPT_CAP); - 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); - stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2); - stream_putc (s, CAPABILITY_CODE_REFRESH); - stream_putc (s, CAPABILITY_CODE_REFRESH_LEN); - - /* AS4 */ - SET_FLAG (peer->cap, PEER_CAP_AS4_ADV); - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2); - stream_putc (s, CAPABILITY_CODE_AS4); - stream_putc (s, CAPABILITY_CODE_AS4_LEN); - if ( peer->change_local_as ) - local_as = peer->change_local_as; - else - local_as = peer->local_as; - stream_putl (s, local_as ); - - /* AddPath */ - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - if (peer->afc[afi][safi]) - { - afi_safi_count++; - - /* Only advertise addpath TX if a feature that will use it is - * configured */ - if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS) || - CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) - adv_addpath_tx = 1; - } - - SET_FLAG (peer->cap, PEER_CAP_ADDPATH_ADV); - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count) + 2); - stream_putc (s, CAPABILITY_CODE_ADDPATH); - stream_putc (s, CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count); - - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - if (peer->afc[afi][safi]) - { - /* Convert AFI, SAFI to values for packet. */ - bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); - - stream_putw (s, pkt_afi); - stream_putc (s, pkt_safi); - - if (adv_addpath_tx) - { - stream_putc (s, BGP_ADDPATH_RX|BGP_ADDPATH_TX); - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV); - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV); - } - else - { - stream_putc (s, BGP_ADDPATH_RX); - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV); - UNSET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV); - } - } - - /* ORF capability. */ - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - 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)) - { - bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD); - bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF); + u_char len; + unsigned long cp, capp, rcapp; + iana_afi_t pkt_afi; + afi_t afi; + safi_t safi, pkt_safi; + as_t local_as; + u_int32_t restart_time; + u_char afi_safi_count = 0; + struct utsname names; + int adv_addpath_tx = 0; + + /* Remember current pointer for Opt Parm Len. */ + cp = stream_get_endp(s); + + /* Opt Parm Len. */ + stream_putc(s, 0); + + /* Do not send capability. */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN) + || CHECK_FLAG(peer->flags, PEER_FLAG_DONT_CAPABILITY)) + return; + + /* MP capability for configured AFI, SAFI */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (peer->afc[afi][safi]) { + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, + &pkt_safi); + + peer->afc_adv[afi][safi] = 1; + stream_putc(s, BGP_OPEN_OPT_CAP); + stream_putc(s, CAPABILITY_CODE_MP_LEN + 2); + stream_putc(s, CAPABILITY_CODE_MP); + stream_putc(s, CAPABILITY_CODE_MP_LEN); + stream_putw(s, pkt_afi); + stream_putc(s, 0); + stream_putc(s, pkt_safi); + + /* Extended nexthop capability - currently + * supporting RFC-5549 for + * Link-Local peering only + */ + if (CHECK_FLAG(peer->flags, + PEER_FLAG_CAPABILITY_ENHE) + && peer->su.sa.sa_family == AF_INET6 + && IN6_IS_ADDR_LINKLOCAL( + &peer->su.sin6.sin6_addr) + && afi == AFI_IP + && (safi == SAFI_UNICAST + || safi == SAFI_LABELED_UNICAST)) { + /* RFC 5549 Extended Next Hop Encoding + */ + SET_FLAG(peer->cap, PEER_CAP_ENHE_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + stream_putc(s, + CAPABILITY_CODE_ENHE_LEN + + 2); + stream_putc(s, CAPABILITY_CODE_ENHE); + stream_putc(s, + CAPABILITY_CODE_ENHE_LEN); + + SET_FLAG(peer->af_cap[AFI_IP][safi], + PEER_CAP_ENHE_AF_ADV); + stream_putw(s, pkt_afi); + stream_putw(s, pkt_safi); + stream_putw(s, afi_int2iana(AFI_IP6)); + + if (CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ENHE_AF_RCV)) + SET_FLAG( + peer->af_cap[afi][safi], + PEER_CAP_ENHE_AF_NEGO); + } + } + } + + /* Route refresh. */ + SET_FLAG(peer->cap, PEER_CAP_REFRESH_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + 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); + stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2); + stream_putc(s, CAPABILITY_CODE_REFRESH); + stream_putc(s, CAPABILITY_CODE_REFRESH_LEN); + + /* AS4 */ + SET_FLAG(peer->cap, PEER_CAP_AS4_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + stream_putc(s, CAPABILITY_CODE_AS4_LEN + 2); + stream_putc(s, CAPABILITY_CODE_AS4); + stream_putc(s, CAPABILITY_CODE_AS4_LEN); + if (peer->change_local_as) + local_as = peer->change_local_as; + else + local_as = peer->local_as; + stream_putl(s, local_as); + + /* AddPath */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (peer->afc[afi][safi]) { + afi_safi_count++; + + /* Only advertise addpath TX if a feature that + * will use it is + * configured */ + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_ALL_PATHS) + || CHECK_FLAG( + peer->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) + adv_addpath_tx = 1; + } + + SET_FLAG(peer->cap, PEER_CAP_ADDPATH_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + stream_putc(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count) + 2); + stream_putc(s, CAPABILITY_CODE_ADDPATH); + stream_putc(s, CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (peer->afc[afi][safi]) { + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, + &pkt_safi); + + stream_putw(s, pkt_afi); + stream_putc(s, pkt_safi); + + if (adv_addpath_tx) { + stream_putc(s, + BGP_ADDPATH_RX + | BGP_ADDPATH_TX); + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_RX_ADV); + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_TX_ADV); + } else { + stream_putc(s, BGP_ADDPATH_RX); + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_RX_ADV); + UNSET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_TX_ADV); + } + } + + /* ORF capability. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + 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)) { + bgp_open_capability_orf( + s, peer, afi, safi, + CAPABILITY_CODE_ORF_OLD); + bgp_open_capability_orf(s, peer, afi, safi, + CAPABILITY_CODE_ORF); + } + + /* Dynamic capability. */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) { + SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + 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); + stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2); + stream_putc(s, CAPABILITY_CODE_DYNAMIC); + stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN); } - /* Dynamic capability. */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) - { - SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV); - stream_putc (s, BGP_OPEN_OPT_CAP); - 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); - stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2); - stream_putc (s, CAPABILITY_CODE_DYNAMIC); - stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN); - } - - /* Hostname capability */ - uname(&names); - if (names.nodename[0] != '\0') - { - SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV); - stream_putc (s, BGP_OPEN_OPT_CAP); - rcapp = stream_get_endp(s); /* Ptr to length placeholder */ - stream_putc(s, 0); /* dummy len for now */ - stream_putc (s, CAPABILITY_CODE_FQDN); - capp = stream_get_endp(s); - stream_putc(s, 0); /* dummy len for now */ - len = strlen(names.nodename); - if (len > BGP_MAX_HOSTNAME) - len = BGP_MAX_HOSTNAME; - - stream_putc(s, len); - stream_put(s, names.nodename, len); + /* Hostname capability */ + uname(&names); + if (names.nodename[0] != '\0') { + SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + rcapp = stream_get_endp(s); /* Ptr to length placeholder */ + stream_putc(s, 0); /* dummy len for now */ + stream_putc(s, CAPABILITY_CODE_FQDN); + capp = stream_get_endp(s); + stream_putc(s, 0); /* dummy len for now */ + len = strlen(names.nodename); + if (len > BGP_MAX_HOSTNAME) + len = BGP_MAX_HOSTNAME; + + stream_putc(s, len); + stream_put(s, names.nodename, len); #ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME - if ((names.domainname[0] != '\0') && - (strcmp(names.domainname, "(none)") != 0)) - { - len = strlen(names.domainname); - if (len > BGP_MAX_HOSTNAME) - len = BGP_MAX_HOSTNAME; - - stream_putc(s, len); - stream_put(s, names.domainname, len); - } - else + if ((names.domainname[0] != '\0') + && (strcmp(names.domainname, "(none)") != 0)) { + len = strlen(names.domainname); + if (len > BGP_MAX_HOSTNAME) + len = BGP_MAX_HOSTNAME; + + stream_putc(s, len); + stream_put(s, names.domainname, len); + } else #endif - { - stream_putc(s, 0); /* 0 length */ - } + { + stream_putc(s, 0); /* 0 length */ + } - /* Set the lengths straight */ - len = stream_get_endp(s) - rcapp - 1; - stream_putc_at(s, rcapp, len); - len = stream_get_endp(s) - capp - 1; - stream_putc_at(s, capp, len); + /* Set the lengths straight */ + len = stream_get_endp(s) - rcapp - 1; + stream_putc_at(s, rcapp, len); + len = stream_get_endp(s) - capp - 1; + stream_putc_at(s, capp, len); - if (bgp_debug_neighbor_events(peer)) + if (bgp_debug_neighbor_events(peer)) #ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME - zlog_debug("%s Sending hostname cap with hn = %s, dn = %s", - peer->host, names.nodename, names.domainname); + zlog_debug( + "%s Sending hostname cap with hn = %s, dn = %s", + peer->host, names.nodename, names.domainname); #else - zlog_debug("%s Sending hostname cap with hn = %s", peer->host, - names.nodename); + zlog_debug("%s Sending hostname cap with hn = %s", + peer->host, names.nodename); #endif - } - - /* Sending base graceful-restart capability irrespective of the config */ - SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV); - stream_putc (s, BGP_OPEN_OPT_CAP); - capp = stream_get_endp (s); /* Set Capability Len Pointer */ - stream_putc (s, 0); /* Capability Length */ - stream_putc (s, CAPABILITY_CODE_RESTART); - rcapp = stream_get_endp (s); /* Set Restart Capability Len Pointer */ - stream_putc (s, 0); - restart_time = peer->bgp->restart_time; - if (peer->bgp->t_startup) - { - SET_FLAG (restart_time, RESTART_R_BIT); - SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_ADV); - } - stream_putw (s, restart_time); - - /* Send address-family specific graceful-restart capability only when GR config - is present */ - if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART)) - { - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - if (peer->afc[afi][safi]) - { - /* Convert AFI, SAFI to values for packet. */ - bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); - stream_putw (s, pkt_afi); - stream_putc (s, pkt_safi); - if (bgp_flag_check(peer->bgp, BGP_FLAG_GR_PRESERVE_FWD)) - stream_putc (s, RESTART_F_BIT); - else - stream_putc (s, 0); - } - } - - /* Total Graceful restart capability Len. */ - len = stream_get_endp (s) - rcapp - 1; - stream_putc_at (s, rcapp, len); - - /* Total Capability Len. */ - len = stream_get_endp (s) - capp - 1; - stream_putc_at (s, capp, len); - - /* Total Opt Parm Len. */ - len = stream_get_endp (s) - cp - 1; - stream_putc_at (s, cp, len); + } + + /* Sending base graceful-restart capability irrespective of the config + */ + SET_FLAG(peer->cap, PEER_CAP_RESTART_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + capp = stream_get_endp(s); /* Set Capability Len Pointer */ + stream_putc(s, 0); /* Capability Length */ + stream_putc(s, CAPABILITY_CODE_RESTART); + rcapp = stream_get_endp(s); /* Set Restart Capability Len Pointer */ + stream_putc(s, 0); + restart_time = peer->bgp->restart_time; + if (peer->bgp->t_startup) { + SET_FLAG(restart_time, RESTART_R_BIT); + SET_FLAG(peer->cap, PEER_CAP_RESTART_BIT_ADV); + } + stream_putw(s, restart_time); + + /* Send address-family specific graceful-restart capability only when GR + config + is present */ + if (bgp_flag_check(peer->bgp, BGP_FLAG_GRACEFUL_RESTART)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (peer->afc[afi][safi]) { + /* Convert AFI, SAFI to values for + * packet. */ + bgp_map_afi_safi_int2iana( + afi, safi, &pkt_afi, &pkt_safi); + stream_putw(s, pkt_afi); + stream_putc(s, pkt_safi); + if (bgp_flag_check( + peer->bgp, + BGP_FLAG_GR_PRESERVE_FWD)) + stream_putc(s, RESTART_F_BIT); + else + stream_putc(s, 0); + } + } + + /* Total Graceful restart capability Len. */ + len = stream_get_endp(s) - rcapp - 1; + stream_putc_at(s, rcapp, len); + + /* Total Capability Len. */ + len = stream_get_endp(s) - capp - 1; + stream_putc_at(s, capp, len); + + /* Total Opt Parm Len. */ + len = stream_get_endp(s) - cp - 1; + stream_putc_at(s, cp, len); } |