📄 bgp_packet.c
字号:
if (peer->status != Established) { zlog_err ("%s [FSM] Update packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status)); bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0); return -1; } /* Set initial values. */ memset (&attr, 0, sizeof (struct attr)); memset (&update, 0, sizeof (struct bgp_nlri)); memset (&withdraw, 0, sizeof (struct bgp_nlri)); memset (&mp_update, 0, sizeof (struct bgp_nlri)); memset (&mp_withdraw, 0, sizeof (struct bgp_nlri)); s = peer->ibuf; end = stream_pnt (s) + size; /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute Length is too large (i.e., if Unfeasible Routes Length + Total Attribute Length + 23 exceeds the message Length), then the Error Subcode is set to Malformed Attribute List. */ if (stream_pnt (s) + 2 > end) { zlog_err ("%s [Error] Update packet error" " (packet length is short for unfeasible length)", peer->host); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MAL_ATTR); return -1; } /* Unfeasible Route Length. */ withdraw_len = stream_getw (s); /* Unfeasible Route Length check. */ if (stream_pnt (s) + withdraw_len > end) { zlog_err ("%s [Error] Update packet error" " (packet unfeasible length overflow %d)", peer->host, withdraw_len); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MAL_ATTR); return -1; } /* Unfeasible Route packet format check. */ if (withdraw_len > 0) { ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len); if (ret < 0) return -1; if (BGP_DEBUG (packet, PACKET_RECV)) zlog_info ("%s [Update:RECV] Unfeasible NLRI received", peer->host); withdraw.afi = AFI_IP; withdraw.safi = SAFI_UNICAST; withdraw.nlri = stream_pnt (s); withdraw.length = withdraw_len; stream_forward (s, withdraw_len); } /* Attribute total length check. */ if (stream_pnt (s) + 2 > end) { zlog_warn ("%s [Error] Packet Error" " (update packet is short for attribute length)", peer->host); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MAL_ATTR); return -1; } /* Fetch attribute total length. */ attribute_len = stream_getw (s); /* Attribute length check. */ if (stream_pnt (s) + attribute_len > end) { zlog_warn ("%s [Error] Packet Error" " (update packet attribute length overflow %d)", peer->host, attribute_len); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MAL_ATTR); return -1; } /* Parse attribute when it exists. */ if (attribute_len) { ret = bgp_attr_parse (peer, &attr, attribute_len, &mp_update, &mp_withdraw); if (ret < 0) return -1; } /* Logging the attribute. */ if (BGP_DEBUG (update, UPDATE_IN)) { ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ); if (ret) zlog (peer->log, LOG_INFO, "%s rcvd UPDATE w/ attr: %s", peer->host, attrstr); } /* Network Layer Reachability Information. */ update_len = end - stream_pnt (s); if (update_len) { /* Check NLRI packet format and prefix length. */ ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len); if (ret < 0) return -1; /* Set NLRI portion to structure. */ update.afi = AFI_IP; update.safi = SAFI_UNICAST; update.nlri = stream_pnt (s); update.length = update_len; stream_forward (s, update_len); } /* NLRI is processed only when the peer is configured specific Address Family and Subsequent Address Family. */ if (peer->afc[AFI_IP][SAFI_UNICAST]) { if (withdraw.length) bgp_nlri_parse (peer, NULL, &withdraw); if (update.length) { /* We check well-known attribute only for IPv4 unicast update. */ ret = bgp_attr_check (peer, &attr); if (ret < 0) return -1; bgp_nlri_parse (peer, &attr, &update); } if (mp_update.length && mp_update.afi == AFI_IP && mp_update.safi == SAFI_UNICAST) bgp_nlri_parse (peer, &attr, &mp_update); if (mp_withdraw.length && mp_withdraw.afi == AFI_IP && mp_withdraw.safi == SAFI_UNICAST) bgp_nlri_parse (peer, NULL, &mp_withdraw); if (! attribute_len && ! withdraw_len) { /* End-of-RIB received */ SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED); if (BGP_DEBUG (normal, NORMAL)) zlog (peer->log, LOG_INFO, "rcvd End-of-RIB for IPv4 Unicast from %s", peer->host); /* NSF delete stale route */ if (peer->nsf[AFI_IP][SAFI_UNICAST]) bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST); } } if (peer->afc[AFI_IP][SAFI_MULTICAST]) { if (mp_update.length && mp_update.afi == AFI_IP && mp_update.safi == SAFI_MULTICAST) bgp_nlri_parse (peer, &attr, &mp_update); if (mp_withdraw.length && mp_withdraw.afi == AFI_IP && mp_withdraw.safi == SAFI_MULTICAST) bgp_nlri_parse (peer, NULL, &mp_withdraw); if (! withdraw_len && mp_withdraw.afi == AFI_IP && mp_withdraw.safi == SAFI_MULTICAST && mp_withdraw.length == 0) { /* End-of-RIB received */ SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST], PEER_STATUS_EOR_RECEIVED); if (BGP_DEBUG (normal, NORMAL)) zlog (peer->log, LOG_INFO, "rcvd End-of-RIB for IPv4 Multicast from %s", peer->host); /* NSF delete stale route */ if (peer->nsf[AFI_IP][SAFI_MULTICAST]) bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST); } } if (peer->afc[AFI_IP6][SAFI_UNICAST]) { if (mp_update.length && mp_update.afi == AFI_IP6 && mp_update.safi == SAFI_UNICAST) bgp_nlri_parse (peer, &attr, &mp_update); if (mp_withdraw.length && mp_withdraw.afi == AFI_IP6 && mp_withdraw.safi == SAFI_UNICAST) bgp_nlri_parse (peer, NULL, &mp_withdraw); if (! withdraw_len && mp_withdraw.afi == AFI_IP6 && mp_withdraw.safi == SAFI_UNICAST && mp_withdraw.length == 0) { /* End-of-RIB received */ SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED); if (BGP_DEBUG (normal, NORMAL)) zlog (peer->log, LOG_INFO, "rcvd End-of-RIB for IPv6 Unicast from %s", peer->host); /* NSF delete stale route */ if (peer->nsf[AFI_IP6][SAFI_UNICAST]) bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST); } } if (peer->afc[AFI_IP6][SAFI_MULTICAST]) { if (mp_update.length && mp_update.afi == AFI_IP6 && mp_update.safi == SAFI_MULTICAST) bgp_nlri_parse (peer, &attr, &mp_update); if (mp_withdraw.length && mp_withdraw.afi == AFI_IP6 && mp_withdraw.safi == SAFI_MULTICAST) bgp_nlri_parse (peer, NULL, &mp_withdraw); if (! withdraw_len && mp_withdraw.afi == AFI_IP6 && mp_withdraw.safi == SAFI_MULTICAST && mp_withdraw.length == 0) { /* End-of-RIB received */ SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_MULTICAST], PEER_STATUS_EOR_RECEIVED); if (BGP_DEBUG (update, UPDATE_IN)) zlog (peer->log, LOG_INFO, "rcvd End-of-RIB for IPv6 Multicast from %s", peer->host); /* NSF delete stale route */ if (peer->nsf[AFI_IP6][SAFI_MULTICAST]) bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST); } } if (peer->afc[AFI_IP][SAFI_MPLS_VPN]) { if (mp_update.length && mp_update.afi == AFI_IP && mp_update.safi == BGP_SAFI_VPNV4) bgp_nlri_parse_vpnv4 (peer, &attr, &mp_update); if (mp_withdraw.length && mp_withdraw.afi == AFI_IP && mp_withdraw.safi == BGP_SAFI_VPNV4) bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw); if (! withdraw_len && mp_withdraw.afi == AFI_IP && mp_withdraw.safi == BGP_SAFI_VPNV4 && mp_withdraw.length == 0) { /* End-of-RIB received */ if (BGP_DEBUG (update, UPDATE_IN)) zlog (peer->log, LOG_INFO, "rcvd End-of-RIB for VPNv4 Unicast from %s", peer->host); } } /* Everything is done. We unintern temporary structures which interned in bgp_attr_parse(). */ if (attr.aspath) aspath_unintern (attr.aspath); if (attr.community) community_unintern (attr.community); if (attr.ecommunity) ecommunity_unintern (attr.ecommunity); if (attr.cluster) cluster_unintern (attr.cluster); if (attr.transit) transit_unintern (attr.transit); /* If peering is stopped due to some reason, do not generate BGP event. */ if (peer->status != Established) return 0; /* Increment packet counter. */ peer->update_in++; peer->update_time = time (NULL); /* Generate BGP event. */ BGP_EVENT_ADD (peer, Receive_UPDATE_message); return 0;}/* Notify message treatment function. */voidbgp_notify_receive (struct peer *peer, bgp_size_t size){ struct bgp_notify bgp_notify; if (peer->notify.data) { XFREE (MTYPE_TMP, peer->notify.data); peer->notify.data = NULL; peer->notify.length = 0; } bgp_notify.code = stream_getc (peer->ibuf); bgp_notify.subcode = stream_getc (peer->ibuf); bgp_notify.length = size - 2; bgp_notify.data = NULL; /* Preserv notify code and sub code. */ peer->notify.code = bgp_notify.code; peer->notify.subcode = bgp_notify.subcode; /* For further diagnostic record returned Data. */ if (bgp_notify.length) { peer->notify.length = size - 2; peer->notify.data = XMALLOC (MTYPE_TMP, size - 2); memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2); } /* For debug */ { int i; int first = 0; char c[4]; if (bgp_notify.length) { bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3); for (i = 0; i < bgp_notify.length; i++) if (first) { sprintf (c, " %02x", stream_getc (peer->ibuf)); strcat (bgp_notify.data, c); } else { first = 1; sprintf (c, "%02x", stream_getc (peer->ibuf)); strcpy (bgp_notify.data, c); } } bgp_notify_print(peer, &bgp_notify, "received"); if (bgp_notify.data) XFREE (MTYPE_TMP, bgp_notify.data); } /* peer count update */ peer->notify_in++; if (peer->status == Established) peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED; /* We have to check for Notify with Unsupported Optional Parameter. in that case we fallback to open without the capability option. But this done in bgp_stop. We just mark it here to avoid changing the fsm tables. */ if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR && bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM ) UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN); /* Also apply to Unsupported Capability until remote router support capability. */ if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR && bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_CAPBL) UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN); BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);}/* Keepalive treatment function -- get keepalive send keepalive */voidbgp_keepalive_receive (struct peer *peer, bgp_size_t size){ if (BGP_DEBUG (keepalive, KEEPALIVE)) zlog_info ("%s KEEPALIVE rcvd", peer->host); BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);}/* Route refresh message is received. */voidbgp_route_refresh_receive (struct peer *peer, bgp_size_t size){ afi_t afi; safi_t safi; u_char reserved; struct stream *s; /* If peer does not have the capability, send notification. */ if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV)) { plog_err (peer->log, "%s [Error] BGP route refresh is not enabled", peer->host); bgp_notify_send (peer, BGP_NOTIFY_HEADER_ERR, BGP_NOTIFY_HEADER_BAD_MESTYPE); return; } /* Status must be Established. */ if (peer->status != Established) { plog_err (peer->log, "%s [Error] Route refresh packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status)); bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0); return; } s = peer->ibuf; /* Parse packet. */ afi = stream_getw (s); reserved = stream_getc (s); safi = stream_getc (s); if (BGP_DEBUG (normal, NORMAL)) zlog_info ("%s rcvd REFRESH_REQ for afi/safi: %d/%d", peer->host, afi, safi); /* Check AFI and SAFI. */ if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != BGP_SAFI_VPNV4)) { if (BGP_DEBUG (normal, NORMAL)) { zlog_info ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored", peer->host, afi, safi); } return; } /* Adjust safi code. */ if (safi == BGP_SAFI_VPNV4) safi = SAFI_MPLS_VPN; if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) { u_char *end; u_char when_to_refresh; u_char orf_type; u_int16_t orf_len; if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5) { zlog_info ("%s ORF route refresh length error", peer->host); bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); return; } when_to_refresh = stream_getc (s); end = stream_pnt (s) + (size - 5); while (stream_pnt (s) < end) { orf_type = stream_getc (s); orf_len = stream_getw (s); if (orf_type == ORF_TYPE_PREFIX || orf_type == ORF_TYPE_PREFIX_OLD) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -