From 3893aeeea3f7c3f0d83e428f23f02fcc02568b1c Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Sun, 15 Mar 2020 14:19:11 +0200 Subject: [PATCH] bgpd: Add subcodes for BGP Finite State Machine Error Implement https://tools.ietf.org/html/rfc6608 I used python scapy library to send a notification message in OpenSent state: ``` send(IP(dst="192.168.0.1")/TCP(sport=sp, dport=179, seq=rec.ack, ack=rec.seq + 1, flags=0x18)/BGPHeader(type=3)/BGPNotification(error_code=4, error_subcode=0)) ``` Logs from FRR: ``` %NOTIFICATION: sent to neighbor 192.168.0.2 5/1 (Neighbor Events Error/Receive Unexpected Message in OpenSent State) 0 bytes ``` Signed-off-by: Donatas Abraitis --- bgpd/bgp_debug.c | 13 ++++++++++++- bgpd/bgp_fsm.c | 29 +++++++++++++++++++++++++---- bgpd/bgp_fsm.h | 1 + bgpd/bgp_packet.c | 6 +++--- bgpd/bgpd.h | 6 ++++++ 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 466fecc581..2e21c7222c 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -170,6 +170,16 @@ static const struct message bgp_notify_capability_msg[] = { {BGP_NOTIFY_CAPABILITY_MALFORMED_CODE, "/Malformed Capability Value"}, {0}}; +static const struct message bgp_notify_fsm_msg[] = { + {BGP_NOTIFY_FSM_ERR_SUBCODE_UNSPECIFIC, "/Unspecific"}, + {BGP_NOTIFY_FSM_ERR_SUBCODE_OPENSENT, + "/Receive Unexpected Message in OpenSent State"}, + {BGP_NOTIFY_FSM_ERR_SUBCODE_OPENCONFIRM, + "/Receive Unexpected Message in OpenConfirm State"}, + {BGP_NOTIFY_FSM_ERR_SUBCODE_ESTABLISHED, + "/Receive Unexpected Message in Established State"}, + {0}}; + /* Origin strings. */ const char *const bgp_origin_str[] = {"i", "e", "?"}; const char *const bgp_origin_long_str[] = {"IGP", "EGP", "incomplete"}; @@ -471,7 +481,8 @@ const char *bgp_notify_subcode_str(char code, char subcode) case BGP_NOTIFY_HOLD_ERR: break; case BGP_NOTIFY_FSM_ERR: - break; + return lookup_msg(bgp_notify_fsm_msg, subcode, + "Unrecognized Error Subcode"); case BGP_NOTIFY_CEASE: return lookup_msg(bgp_notify_cease_msg, subcode, "Unrecognized Error Subcode"); diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 71e2b02602..3060e625ca 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -885,6 +885,27 @@ void bgp_maxmed_update(struct bgp *bgp) } } +int bgp_fsm_error_subcode(int status) +{ + int fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_UNSPECIFIC; + + switch (status) { + case OpenSent: + fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_OPENSENT; + break; + case OpenConfirm: + fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_OPENCONFIRM; + break; + case Established: + fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_ESTABLISHED; + break; + default: + break; + } + + return fsm_err_subcode; +} + /* The maxmed onstartup timer expiry callback. */ static int bgp_maxmed_onstartup_timer(struct thread *thread) { @@ -1455,9 +1476,8 @@ static int bgp_connect_success(struct peer *peer) flog_err_sys(EC_LIB_SOCKET, "%s: bgp_getsockname(): failed for peer %s, fd %d", __func__, peer->host, peer->fd); - bgp_notify_send( - peer, BGP_NOTIFY_FSM_ERR, - BGP_NOTIFY_SUBCODE_UNSPECIFIC); /* internal error */ + bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, + bgp_fsm_error_subcode(peer->status)); bgp_writes_on(peer); return -1; } @@ -1657,7 +1677,8 @@ static int bgp_fsm_event_error(struct peer *peer) flog_err(EC_BGP_FSM, "%s [FSM] unexpected packet received in state %s", peer->host, lookup_msg(bgp_status_msg, peer->status, NULL)); - return bgp_stop_with_notify(peer, BGP_NOTIFY_FSM_ERR, 0); + return bgp_stop_with_notify(peer, BGP_NOTIFY_FSM_ERR, + bgp_fsm_error_subcode(peer->status)); } /* Hold timer expire. This is error of BGP connection. So cut the diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h index 6feabbf570..4b8db161d7 100644 --- a/bgpd/bgp_fsm.h +++ b/bgpd/bgp_fsm.h @@ -121,6 +121,7 @@ extern void bgp_update_delay_end(struct bgp *); extern void bgp_maxmed_update(struct bgp *); extern int bgp_maxmed_onstartup_configured(struct bgp *); extern int bgp_maxmed_onstartup_active(struct bgp *); +extern int bgp_fsm_error_subcode(int status); /** * Start the route advertisement timer (that honors MRAI) for all the diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 0e251dced8..a7b2bc3458 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1447,7 +1447,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size) peer->host, lookup_msg(bgp_status_msg, peer->status, NULL)); bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, - BGP_NOTIFY_SUBCODE_UNSPECIFIC); + bgp_fsm_error_subcode(peer->status)); return BGP_Stop; } @@ -1859,7 +1859,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size) peer->host, lookup_msg(bgp_status_msg, peer->status, NULL)); bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, - BGP_NOTIFY_SUBCODE_UNSPECIFIC); + bgp_fsm_error_subcode(peer->status)); return BGP_Stop; } @@ -2251,7 +2251,7 @@ int bgp_capability_receive(struct peer *peer, bgp_size_t size) peer->host, lookup_msg(bgp_status_msg, peer->status, NULL)); bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, - BGP_NOTIFY_SUBCODE_UNSPECIFIC); + bgp_fsm_error_subcode(peer->status)); return BGP_Stop; } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 1ada056a92..769ac32653 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1499,6 +1499,12 @@ struct bgp_nlri { #define BGP_NOTIFY_CEASE 6 #define BGP_NOTIFY_CAPABILITY_ERR 7 +/* Subcodes for BGP Finite State Machine Error */ +#define BGP_NOTIFY_FSM_ERR_SUBCODE_UNSPECIFIC 0 +#define BGP_NOTIFY_FSM_ERR_SUBCODE_OPENSENT 1 +#define BGP_NOTIFY_FSM_ERR_SUBCODE_OPENCONFIRM 2 +#define BGP_NOTIFY_FSM_ERR_SUBCODE_ESTABLISHED 3 + #define BGP_NOTIFY_SUBCODE_UNSPECIFIC 0 /* BGP_NOTIFY_HEADER_ERR sub codes. */ -- 2.39.5