diff --git a/RFCs.md b/RFCs.md index acca2b38..a318a239 100644 --- a/RFCs.md +++ b/RFCs.md @@ -7,6 +7,7 @@ Please keep this list ordered. * 4271 A Border Gateway Protocol 4 (BGP-4) * 4456 BGP Route Reflection * 4760 Multiprotocol Extensions for BGP-4 + * 6286 Autonomous-System-Wide Unique BGP Identifier for BGP-4 * 6793 32bit ASNs * 7854 BGP Monitoring Protocol (BMP) * 7911 BGP AddPath diff --git a/protocols/bgp/server/fsm_open_sent.go b/protocols/bgp/server/fsm_open_sent.go index 96600518..07f113a2 100644 --- a/protocols/bgp/server/fsm_open_sent.go +++ b/protocols/bgp/server/fsm_open_sent.go @@ -124,6 +124,14 @@ func (s *openSentState) openMsgReceived(openMsg *packet.BGPOpen) (state, string) return s.handleOpenMessage(openMsg) } + // RFC6286, Sect 2.2: If the BGP Identifier field of the OPEN message is zero, + // or if it is the same as the BGP Identifier of the local BGP speaker and the + // message is from an internal peer, then the Error Subcode is set to "Bad BGP Identifier". + if openMsg.BGPIdentifier == 0 || (s.fsm.peer.localASN == s.fsm.peer.peerASN && s.fsm.peer.routerID == openMsg.BGPIdentifier) { + s.fsm.sendNotification(packet.OpenMessageError, packet.BadBGPIdentifier) + return newIdleState(s.fsm), fmt.Sprintf("Bad BGP Identifier %d", openMsg.BGPIdentifier) + } + stopTimer(s.fsm.connectRetryTimer) if s.fsm.peer.collisionHandling(s.fsm) { return s.cease() diff --git a/protocols/bgp/server/peer.go b/protocols/bgp/server/peer.go index 432a7b5e..aaaa9dc4 100644 --- a/protocols/bgp/server/peer.go +++ b/protocols/bgp/server/peer.go @@ -234,7 +234,7 @@ func (p *peer) collisionHandling(callingFSM *FSM) bool { continue } - if p.routerID < callingFSM.neighborID { + if p.shouldCeaseOnCollision(callingFSM) { fsm.cease() } else { return true @@ -244,6 +244,24 @@ func (p *peer) collisionHandling(callingFSM *FSM) bool { return false } +func (p *peer) shouldCeaseOnCollision(callingFSM *FSM) bool { + // RFC6286: For a BGP speaker that supports the AS-wide Unique BGP Identifier, + // the procedures for connection collision resolution are extended as + // follows to deal with the case in which the two BGP speakers share the + // same BGP Identifier (thus, it is only applicable to an external + // peer): + // + // If the BGP Identifiers of the peers involved in the connection + // collision are identical, then the connection initiated by the BGP + // speaker with the larger AS number is preserved. + if p.routerID == callingFSM.neighborID { + return p.localASN < callingFSM.peer.peerASN + } + + // RFC4271 collision handling + return p.routerID < callingFSM.neighborID +} + func isOpenConfirmState(s state) bool { switch s.(type) { case openConfirmState: