diff --git a/protocols/bmp/packet/decode.go b/protocols/bmp/packet/decode.go index 581411d64ec782636245a159b2545babf68f720d..d7989e28bb5955a294b195962d06c980cd0b645b 100644 --- a/protocols/bmp/packet/decode.go +++ b/protocols/bmp/packet/decode.go @@ -99,6 +99,4 @@ func Decode(msg []byte) (Msg, error) { return nil, fmt.Errorf("Unexpected message type: %d", ch.MsgType) } - - return nil, fmt.Errorf("Unexpected message type: %d", ch.MsgType) } diff --git a/protocols/bmp/packet/initiation_message.go b/protocols/bmp/packet/initiation_message.go index 076d0f4b8a7c9713b1f75a76086c310140daf28f..6d4ee7ecc707702bfa4277901cab76be56c826a8 100644 --- a/protocols/bmp/packet/initiation_message.go +++ b/protocols/bmp/packet/initiation_message.go @@ -18,7 +18,8 @@ func (im *InitiationMessage) MsgType() uint8 { func decodeInitiationMessage(buf *bytes.Buffer, ch *CommonHeader) (Msg, error) { im := &InitiationMessage{ - TLVs: make([]*InformationTLV, 0, 2), + CommonHeader: ch, + TLVs: make([]*InformationTLV, 0, 2), } read := uint32(0) diff --git a/protocols/bmp/packet/peer_down.go b/protocols/bmp/packet/peer_down.go index 347ffa2c51df7a371506183a30f3683df875795f..27f75c4be59822816e4f714e07920fc6935ee630 100644 --- a/protocols/bmp/packet/peer_down.go +++ b/protocols/bmp/packet/peer_down.go @@ -2,15 +2,17 @@ package packet import ( "bytes" + "fmt" "github.com/bio-routing/bio-rd/util/decoder" ) // PeerDownNotification represents a peer down notification type PeerDownNotification struct { - CommonHeader *CommonHeader - Reason uint8 - Data []byte + CommonHeader *CommonHeader + PerPeerHeader *PerPeerHeader + Reason uint8 + Data []byte } // MsgType returns the type of this message @@ -19,13 +21,22 @@ func (p *PeerDownNotification) MsgType() uint8 { } func decodePeerDownNotification(buf *bytes.Buffer, ch *CommonHeader) (*PeerDownNotification, error) { - p := &PeerDownNotification{} + p := &PeerDownNotification{ + CommonHeader: ch, + } + + pph, err := decodePerPeerHeader(buf) + if err != nil { + return nil, fmt.Errorf("Unable to decode per peer header: %v", err) + } + + p.PerPeerHeader = pph fields := []interface{}{ &p.Reason, } - err := decoder.Decode(buf, fields) + err = decoder.Decode(buf, fields) if err != nil { return nil, err } @@ -34,7 +45,7 @@ func decodePeerDownNotification(buf *bytes.Buffer, ch *CommonHeader) (*PeerDownN return p, nil } - p.Data = make([]byte, ch.MsgLength-CommonHeaderLen-1) + p.Data = make([]byte, ch.MsgLength-PerPeerHeaderLen-CommonHeaderLen-1) fields = []interface{}{ p.Data, } diff --git a/protocols/bmp/packet/peer_down_test.go b/protocols/bmp/packet/peer_down_test.go index 61f2e9a6d76ee3900c55ba32851e900d57fcb698..b1df8b55e84d9ae6bf5854e4a2aea51357d73c3a 100644 --- a/protocols/bmp/packet/peer_down_test.go +++ b/protocols/bmp/packet/peer_down_test.go @@ -30,14 +30,36 @@ func TestDecodePeerDownNotification(t *testing.T) { { name: "Full", input: []byte{ + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, + 1, 1, 2, 3, }, ch: &CommonHeader{ - MsgLength: CommonHeaderLen + 4, + MsgLength: CommonHeaderLen + 4 + 38, }, wantFail: false, expected: &PeerDownNotification{ + CommonHeader: &CommonHeader{ + MsgLength: CommonHeaderLen + 4 + 38, + }, + PerPeerHeader: &PerPeerHeader{ + PeerType: 1, + PeerFlags: 2, + PeerDistinguisher: 3, + PeerAddress: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + PeerAS: 51324, + PeerBGPID: 123, + Timestamp: 100, + TimestampMicroSeconds: 200, + }, Reason: 1, Data: []byte{ 1, 2, 3, @@ -47,20 +69,65 @@ func TestDecodePeerDownNotification(t *testing.T) { { name: "Full no data", input: []byte{ + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, 4, }, ch: &CommonHeader{ - MsgLength: CommonHeaderLen + 4, + MsgLength: CommonHeaderLen + PerPeerHeaderLen + 4, }, wantFail: false, expected: &PeerDownNotification{ + CommonHeader: &CommonHeader{ + MsgLength: CommonHeaderLen + PerPeerHeaderLen + 4, + }, + PerPeerHeader: &PerPeerHeader{ + PeerType: 1, + PeerFlags: 2, + PeerDistinguisher: 3, + PeerAddress: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + PeerAS: 51324, + PeerBGPID: 123, + Timestamp: 100, + TimestampMicroSeconds: 200, + }, Reason: 4, Data: nil, }, }, + { + name: "Incomplete per peer header", + input: []byte{ + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, + }, + ch: &CommonHeader{ + MsgLength: CommonHeaderLen + 5, + }, + wantFail: true, + }, { name: "Incomplete data", input: []byte{ + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, + 1, 1, 2, 3, }, diff --git a/protocols/bmp/packet/peer_up.go b/protocols/bmp/packet/peer_up.go index 8675fdc92f0f88b4d68941aca28bd510f8add28d..58adc4cc5e6cd294c88758333f6aa26c214f46b0 100644 --- a/protocols/bmp/packet/peer_up.go +++ b/protocols/bmp/packet/peer_up.go @@ -8,12 +8,14 @@ import ( ) const ( + // OpenMsgMinLen is the minimal length of a BGP open message OpenMsgMinLen = 10 ) // PeerUpNotification represents a peer up notification type PeerUpNotification struct { CommonHeader *CommonHeader + PerPeerHeader *PerPeerHeader LocalAddress [16]byte LocalPort uint16 RemotePort uint16 @@ -28,7 +30,16 @@ func (p *PeerUpNotification) MsgType() uint8 { } func decodePeerUpNotification(buf *bytes.Buffer, ch *CommonHeader) (*PeerUpNotification, error) { - p := &PeerUpNotification{} + p := &PeerUpNotification{ + CommonHeader: ch, + } + + pph, err := decodePerPeerHeader(buf) + if err != nil { + return nil, fmt.Errorf("Unable to decode per peer header: %v", err) + } + + p.PerPeerHeader = pph fields := []interface{}{ &p.LocalAddress, @@ -36,7 +47,7 @@ func decodePeerUpNotification(buf *bytes.Buffer, ch *CommonHeader) (*PeerUpNotif &p.RemotePort, } - err := decoder.Decode(buf, fields) + err = decoder.Decode(buf, fields) if err != nil { return nil, err } diff --git a/protocols/bmp/packet/peer_up_test.go b/protocols/bmp/packet/peer_up_test.go index 6f7578fb899163c4e45c99ab41e200bfd905f45a..d29ec7550cc757ee8e3332d1de69509e590948bd 100644 --- a/protocols/bmp/packet/peer_up_test.go +++ b/protocols/bmp/packet/peer_up_test.go @@ -29,6 +29,15 @@ func TestDecodePeerUp(t *testing.T) { { name: "Full", input: []byte{ + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 100, 0, 200, @@ -55,6 +64,19 @@ func TestDecodePeerUp(t *testing.T) { }, wantFail: false, expected: &PeerUpNotification{ + CommonHeader: &CommonHeader{ + MsgLength: 47, + }, + PerPeerHeader: &PerPeerHeader{ + PeerType: 1, + PeerFlags: 2, + PeerDistinguisher: 3, + PeerAddress: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + PeerAS: 51324, + PeerBGPID: 123, + Timestamp: 100, + TimestampMicroSeconds: 200, + }, LocalAddress: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, LocalPort: 100, RemotePort: 200, @@ -82,6 +104,15 @@ func TestDecodePeerUp(t *testing.T) { { name: "Full #2", input: []byte{ + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 100, 0, 200, @@ -106,6 +137,19 @@ func TestDecodePeerUp(t *testing.T) { }, wantFail: false, expected: &PeerUpNotification{ + CommonHeader: &CommonHeader{ + MsgLength: 44, + }, + PerPeerHeader: &PerPeerHeader{ + PeerType: 1, + PeerFlags: 2, + PeerDistinguisher: 3, + PeerAddress: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + PeerAS: 51324, + PeerBGPID: 123, + Timestamp: 100, + TimestampMicroSeconds: 200, + }, LocalAddress: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, LocalPort: 100, RemotePort: 200, @@ -127,9 +171,33 @@ func TestDecodePeerUp(t *testing.T) { }, }, }, + { + name: "Incomplete #0", + input: []byte{ + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, + }, + ch: &CommonHeader{ + MsgLength: 47, + }, + wantFail: true, + }, { name: "Incomplete #1", input: []byte{ + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 100, }, @@ -141,6 +209,15 @@ func TestDecodePeerUp(t *testing.T) { { name: "Incomplete #2", input: []byte{ + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 100, 0, 200, @@ -158,6 +235,14 @@ func TestDecodePeerUp(t *testing.T) { { name: "Incomplete #3", input: []byte{ + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 100, 0, 200, diff --git a/protocols/bmp/packet/termination_message.go b/protocols/bmp/packet/termination_message.go index 8bf69afe3315ce38b26a4512f0ffc851c8a24af6..8021fbebacfce9b8f642c2493fedd39acc9a45f6 100644 --- a/protocols/bmp/packet/termination_message.go +++ b/protocols/bmp/packet/termination_message.go @@ -18,7 +18,8 @@ func (t *TerminationMessage) MsgType() uint8 { func decodeTerminationMessage(buf *bytes.Buffer, ch *CommonHeader) (*TerminationMessage, error) { tm := &TerminationMessage{ - TLVs: make([]*InformationTLV, 0, 2), + CommonHeader: ch, + TLVs: make([]*InformationTLV, 0, 2), } read := uint32(0)