diff options
Diffstat (limited to 'bgpd/bgp_open.c')
-rw-r--r-- | bgpd/bgp_open.c | 195 |
1 files changed, 102 insertions, 93 deletions
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 37595817..80b90683 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -29,6 +29,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "memory.h" #include "bgpd/bgpd.h" + +#include "bgpd/bgp_peer.h" + #include "bgpd/bgp_attr.h" #include "bgpd/bgp_debug.h" #include "bgpd/bgp_fsm.h" @@ -55,14 +58,18 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer) struct capability_mp_data mpc; struct capability_header *hdr; - pnt = peer->notify.data; - end = pnt + peer->notify.length; - + if ((peer == NULL) || (peer->session == NULL) + || (peer->session->notification == NULL)) + return; + + pnt = (char*)peer->session->notification->data; + end = pnt + peer->session->notification->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; @@ -109,14 +116,14 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer) vty_out (vty, " Capability error: vendor specific capability code %d", hdr->code); else - vty_out (vty, " Capability error: unknown capability code %d", + vty_out (vty, " Capability error: unknown capability code %d", hdr->code); pnt += hdr->length + 2; } } -static void +void bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc) { mpc->afi = stream_getw (s); @@ -134,7 +141,7 @@ bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi) zlog_warn ("Invalid afi/safi combination (%u/%u)", afi, *safi); return 0; } - + switch (afi) { case AFI_IP: @@ -154,7 +161,7 @@ bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi) } } zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi); - + return 0; } @@ -164,22 +171,22 @@ bgp_capability_mp (struct peer *peer, struct capability_header *hdr) { struct capability_mp_data mpc; struct stream *s = BGP_INPUT (peer); - + bgp_capability_mp_data (s, &mpc); - + if (BGP_DEBUG (normal, NORMAL)) zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u", peer->host, mpc.afi, mpc.safi); - + if (!bgp_afi_safi_valid_indices (mpc.afi, &mpc.safi)) return -1; - + /* Now safi remapped, and afi/safi are valid array indices */ peer->afc_recv[mpc.afi][mpc.safi] = 1; - + if (peer->afc[mpc.afi][mpc.safi]) peer->afc_nego[mpc.afi][mpc.safi] = 1; - else + else return -1; return 0; @@ -194,21 +201,21 @@ bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi, peer->host, afi, safi, type, mode); } -static const struct message orf_type_str[] = +const struct message orf_type_str[] = { { ORF_TYPE_PREFIX, "Prefixlist" }, { ORF_TYPE_PREFIX_OLD, "Prefixlist (old)" }, }; -static const int orf_type_str_max +const int orf_type_str_max = sizeof(orf_type_str)/sizeof(orf_type_str[0]); -static const struct message orf_mode_str[] = +const struct message orf_mode_str[] = { { ORF_MODE_RECEIVE, "Receive" }, { ORF_MODE_SEND, "Send" }, { ORF_MODE_BOTH, "Both" }, }; -static const int orf_mode_str_max +const int orf_mode_str_max = sizeof(orf_mode_str)/sizeof(orf_mode_str[0]); static int @@ -221,7 +228,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) 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 */ + u_int16_t rm_cap = 0; /* capability receive-mode receive */ int i; /* ORF Entry header */ @@ -229,7 +236,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) entry.num = stream_getc (s); afi = entry.mpc.afi; safi = entry.mpc.safi; - + if (BGP_DEBUG (normal, NORMAL)) zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u", peer->host, entry.mpc.afi, entry.mpc.safi); @@ -242,14 +249,15 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) peer->host, entry.mpc.afi, entry.mpc.safi); return 0; } - + /* validate number field */ if (sizeof (struct capability_orf_entry) + (entry.num * 2) > hdr->length) { zlog_info ("%s ORF Capability entry length error," " Cap length %u, num %u", - peer->host, hdr->length, entry.num); - bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); + peer->host, hdr->length, entry.num) ; + /* TODO: is this the right notification ?? */ + bgp_peer_down_error (peer, BGP_NOTIFY_CEASE, 0); return -1; } @@ -257,7 +265,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) { type = stream_getc(s); mode = stream_getc(s); - + /* ORF Mode error check */ switch (mode) { @@ -297,7 +305,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) bgp_capability_orf_not_support (peer, afi, safi, type, mode); continue; } - + /* AFI vs SAFI */ if (!((afi == AFI_IP && safi == SAFI_UNICAST) || (afi == AFI_IP && safi == SAFI_MULTICAST) @@ -306,7 +314,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) bgp_capability_orf_not_support (peer, afi, safi, type, mode); continue; } - + if (BGP_DEBUG (normal, NORMAL)) zlog_debug ("%s OPEN has %s ORF capability" " as %s for afi/safi: %d/%d", @@ -352,9 +360,9 @@ bgp_capability_orf (struct peer *peer, struct capability_header *hdr) { struct stream *s = BGP_INPUT (peer); size_t end = stream_get_getp (s) + hdr->length; - + assert (stream_get_getp(s) + sizeof(struct capability_orf_entry) <= end); - + /* We must have at least one ORF entry, as the caller has already done * minimum length validation for the capability code - for ORF there must * at least one ORF entry (header and unknown number of pairs of bytes). @@ -363,9 +371,9 @@ bgp_capability_orf (struct peer *peer, struct capability_header *hdr) { if (bgp_capability_orf_entry (peer, hdr) == -1) return -1; - } + } while (stream_get_getp(s) + sizeof(struct capability_orf_entry) < end); - + return 0; } @@ -397,7 +405,7 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr) afi_t afi = stream_getw (s); safi_t safi = stream_getc (s); u_char flag = stream_getc (s); - + if (!bgp_afi_safi_valid_indices (afi, &safi)) { if (BGP_DEBUG (normal, NORMAL)) @@ -424,7 +432,7 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr) 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; @@ -434,16 +442,16 @@ static as_t bgp_capability_as4 (struct peer *peer, struct capability_header *hdr) { 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); SET_FLAG (peer->cap, PEER_CAP_AS4_RCV); - + return as4; } -static const struct message capcode_str[] = +const struct message capcode_str[] = { { CAPABILITY_CODE_MP, "MultiProtocol Extensions" }, { CAPABILITY_CODE_REFRESH, "Route Refresh" }, @@ -454,10 +462,10 @@ static const struct message capcode_str[] = { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" }, { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" }, }; -static const int capcode_str_max = sizeof(capcode_str)/sizeof(capcode_str[0]); +const int capcode_str_max = sizeof(capcode_str)/sizeof(capcode_str[0]); /* Minimum sizes for length field of each cap (so not inc. the header) */ -static const size_t cap_minsizes[] = +const size_t cap_minsizes[] = { [CAPABILITY_CODE_MP] = sizeof (struct capability_mp_data), [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN, @@ -478,41 +486,43 @@ bgp_capability_parse (struct peer *peer, size_t length, 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; - + /* 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_CEASE, 0); + /* TODO: Is this the right notification ?? */ + bgp_peer_down_error (peer, BGP_NOTIFY_CEASE, 0); 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_CEASE, 0); + /* TODO: Is this the right notification ?? */ + bgp_peer_down_error (peer, BGP_NOTIFY_CEASE, 0); return -1; } - + if (BGP_DEBUG (normal, NORMAL)) zlog_debug ("%s OPEN has %s capability (%u), length %u", peer->host, LOOKUP (capcode_str, caphdr.code), caphdr.code, caphdr.length); - + /* Length sanity check, type-specific, for known capabilities */ switch (caphdr.code) { @@ -529,18 +539,19 @@ bgp_capability_parse (struct peer *peer, size_t length, u_char **error) { zlog_info ("%s %s Capability length error: got %u," " expected at least %u", - peer->host, + peer->host, LOOKUP (capcode_str, caphdr.code), - caphdr.length, + caphdr.length, (unsigned) cap_minsizes[caphdr.code]); - bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); + /* TODO: Is this the right notification ?? */ + bgp_peer_down_error (peer, BGP_NOTIFY_CEASE, 0); return -1; } /* we deliberately ignore unknown codes, see below */ default: break; } - + switch (caphdr.code) { case CAPABILITY_CODE_MP: @@ -590,7 +601,7 @@ bgp_capability_parse (struct peer *peer, size_t length, u_char **error) */ if (!bgp_capability_as4 (peer, &caphdr)) return -1; - break; + break; default: if (caphdr.code > 128) { @@ -622,9 +633,8 @@ bgp_capability_parse (struct peer *peer, size_t length, u_char **error) static int bgp_auth_parse (struct peer *peer, size_t length) { - bgp_notify_send (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_AUTH_FAILURE); + bgp_peer_down_error (peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_AUTH_FAILURE); return -1; } @@ -650,7 +660,7 @@ peek_for_as4_capability (struct peer *peer, u_char length) size_t orig_getp = stream_get_getp (s); size_t end = orig_getp + length; as_t as4 = 0; - + /* The full capability parser will better flag the error.. */ if (STREAM_READABLE(s) < length) return 0; @@ -662,40 +672,40 @@ peek_for_as4_capability (struct peer *peer, u_char length) /* the error cases we DONT handle, we ONLY try to read as4 out of * correctly formatted options. */ - while (stream_get_getp(s) < end) + 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; @@ -703,11 +713,11 @@ peek_for_as4_capability (struct peer *peer, u_char length) { if (hdr.length != CAPABILITY_CODE_AS4_LEN) goto end; - + 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); @@ -736,29 +746,31 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *capability) if (BGP_DEBUG (normal, NORMAL)) 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_CEASE, 0); + /* TODO: Is this the right notification ?? */ + bgp_peer_down_error (peer, BGP_NOTIFY_CEASE, 0); 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_CEASE, 0); + /* TODO: Is this the right notification ?? */ + bgp_peer_down_error (peer, BGP_NOTIFY_CEASE, 0); return -1; } @@ -768,7 +780,7 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *capability) 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: @@ -779,9 +791,8 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *capability) *capability = 1; break; default: - bgp_notify_send (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNSUP_PARAM); + bgp_peer_down_error (peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNSUP_PARAM); ret = -1; break; } @@ -801,10 +812,10 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *capability) /* 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); + bgp_peer_down_error_with_data (peer, + BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNSUP_CAPBL, + error_data, error - error_data); return -1; } @@ -812,9 +823,8 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *capability) peer. */ if (! strict_capability_same (peer)) { - bgp_notify_send (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNSUP_CAPBL); + bgp_peer_down_error (peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNSUP_CAPBL); return -1; } } @@ -823,7 +833,7 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *capability) error. */ if (*capability && ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) { - if (! peer->afc_nego[AFI_IP][SAFI_UNICAST] + if (! peer->afc_nego[AFI_IP][SAFI_UNICAST] && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST] && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST] @@ -833,14 +843,13 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *capability) if (error != error_data) - bgp_notify_send_with_data (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNSUP_CAPBL, - error_data, error - error_data); + bgp_peer_down_error_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); + bgp_peer_down_error (peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNSUP_CAPBL); return -1; } } @@ -929,8 +938,8 @@ bgp_open_capability (struct stream *s, struct peer *peer) 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)) + if (// ! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN) || + CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY)) return; /* IPv4 unicast. */ |