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 <donatas.abraitis@gmail.com>
This commit is contained in:
Donatas Abraitis 2020-03-15 14:19:11 +02:00
parent 7d76c335d8
commit 3893aeeea3
5 changed files with 47 additions and 8 deletions

View file

@ -170,6 +170,16 @@ static const struct message bgp_notify_capability_msg[] = {
{BGP_NOTIFY_CAPABILITY_MALFORMED_CODE, "/Malformed Capability Value"}, {BGP_NOTIFY_CAPABILITY_MALFORMED_CODE, "/Malformed Capability Value"},
{0}}; {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. */ /* Origin strings. */
const char *const bgp_origin_str[] = {"i", "e", "?"}; const char *const bgp_origin_str[] = {"i", "e", "?"};
const char *const bgp_origin_long_str[] = {"IGP", "EGP", "incomplete"}; 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: case BGP_NOTIFY_HOLD_ERR:
break; break;
case BGP_NOTIFY_FSM_ERR: case BGP_NOTIFY_FSM_ERR:
break; return lookup_msg(bgp_notify_fsm_msg, subcode,
"Unrecognized Error Subcode");
case BGP_NOTIFY_CEASE: case BGP_NOTIFY_CEASE:
return lookup_msg(bgp_notify_cease_msg, subcode, return lookup_msg(bgp_notify_cease_msg, subcode,
"Unrecognized Error Subcode"); "Unrecognized Error Subcode");

View file

@ -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. */ /* The maxmed onstartup timer expiry callback. */
static int bgp_maxmed_onstartup_timer(struct thread *thread) 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, flog_err_sys(EC_LIB_SOCKET,
"%s: bgp_getsockname(): failed for peer %s, fd %d", "%s: bgp_getsockname(): failed for peer %s, fd %d",
__func__, peer->host, peer->fd); __func__, peer->host, peer->fd);
bgp_notify_send( bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
peer, BGP_NOTIFY_FSM_ERR, bgp_fsm_error_subcode(peer->status));
BGP_NOTIFY_SUBCODE_UNSPECIFIC); /* internal error */
bgp_writes_on(peer); bgp_writes_on(peer);
return -1; 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", flog_err(EC_BGP_FSM, "%s [FSM] unexpected packet received in state %s",
peer->host, lookup_msg(bgp_status_msg, peer->status, NULL)); 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 /* Hold timer expire. This is error of BGP connection. So cut the

View file

@ -121,6 +121,7 @@ extern void bgp_update_delay_end(struct bgp *);
extern void bgp_maxmed_update(struct bgp *); extern void bgp_maxmed_update(struct bgp *);
extern int bgp_maxmed_onstartup_configured(struct bgp *); extern int bgp_maxmed_onstartup_configured(struct bgp *);
extern int bgp_maxmed_onstartup_active(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 * Start the route advertisement timer (that honors MRAI) for all the

View file

@ -1447,7 +1447,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
peer->host, peer->host,
lookup_msg(bgp_status_msg, peer->status, NULL)); lookup_msg(bgp_status_msg, peer->status, NULL));
bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
BGP_NOTIFY_SUBCODE_UNSPECIFIC); bgp_fsm_error_subcode(peer->status));
return BGP_Stop; return BGP_Stop;
} }
@ -1859,7 +1859,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
peer->host, peer->host,
lookup_msg(bgp_status_msg, peer->status, NULL)); lookup_msg(bgp_status_msg, peer->status, NULL));
bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
BGP_NOTIFY_SUBCODE_UNSPECIFIC); bgp_fsm_error_subcode(peer->status));
return BGP_Stop; return BGP_Stop;
} }
@ -2251,7 +2251,7 @@ int bgp_capability_receive(struct peer *peer, bgp_size_t size)
peer->host, peer->host,
lookup_msg(bgp_status_msg, peer->status, NULL)); lookup_msg(bgp_status_msg, peer->status, NULL));
bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
BGP_NOTIFY_SUBCODE_UNSPECIFIC); bgp_fsm_error_subcode(peer->status));
return BGP_Stop; return BGP_Stop;
} }

View file

@ -1499,6 +1499,12 @@ struct bgp_nlri {
#define BGP_NOTIFY_CEASE 6 #define BGP_NOTIFY_CEASE 6
#define BGP_NOTIFY_CAPABILITY_ERR 7 #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 #define BGP_NOTIFY_SUBCODE_UNSPECIFIC 0
/* BGP_NOTIFY_HEADER_ERR sub codes. */ /* BGP_NOTIFY_HEADER_ERR sub codes. */