1// Copyright 2017 Google, Inc. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style license
4// that can be found in the LICENSE file in the root of the source
5// tree.
6//
7//******************************************************************************
8
9package layers
10
11import (
12	"github.com/google/gopacket"
13	"reflect"
14	"testing"
15)
16
17//******************************************************************************
18
19// checkBFD() uses the bfd.go code to analyse the packet bytes as an BFD Control
20// packet and generate an BFD object. It then compares the generated BFD object
21// with the one provided and throws an error if there is any difference.
22// The desc argument is output with any failure message to identify the test.
23func checkBFD(desc string, t *testing.T, packetBytes []byte, pExpectedBFD *BFD) {
24
25	// Analyse the packet bytes, yielding a new packet object p.
26	p := gopacket.NewPacket(packetBytes, LinkTypeEthernet, gopacket.Default)
27	if p.ErrorLayer() != nil {
28		t.Errorf("Failed to decode packet %s: %v", desc, p.ErrorLayer().Error())
29	}
30
31	// Ensure that the packet analysis yielded the correct set of layers:
32	//    Link Layer        = Ethernet.
33	//    Network Layer     = IPv4.
34	//    Transport Layer   = UDP.
35	//    Application Layer = BFD.
36	checkLayers(p, []gopacket.LayerType{
37		LayerTypeEthernet,
38		LayerTypeIPv4,
39		LayerTypeUDP,
40		LayerTypeBFD}, t)
41
42	// Select the Application (BFD) layer.
43	pResultBFD, ok := p.ApplicationLayer().(*BFD)
44	if !ok {
45		t.Error("No BFD layer type found in packet in " + desc + ".")
46	}
47
48	// Compare the generated BFD object with the expected BFD object.
49	if !reflect.DeepEqual(pResultBFD, pExpectedBFD) {
50		t.Errorf("BFD packet processing failed for packet "+desc+
51			":\ngot  :\n%#v\n\nwant :\n%#v\n\n", pResultBFD, pExpectedBFD)
52	}
53	buf := gopacket.NewSerializeBuffer()
54	opts := gopacket.SerializeOptions{}
55	err := pResultBFD.SerializeTo(buf, opts)
56	if err != nil {
57		t.Error(err)
58	}
59	if !reflect.DeepEqual(pResultBFD.Contents, buf.Bytes()) {
60		t.Errorf("BFD packet serialization failed for packet "+desc+
61			":\ngot  :\n%+v\n\nwant :\n%+v\n\n", buf.Bytes(), pResultBFD.Contents)
62	}
63
64}
65
66func TestBFDNoAuth(t *testing.T) {
67	// This test packet is based off of the first BFD packet in the BFD sample capture
68	// pcap file bfd-raw-auth-simple.pcap on the Wireshark sample captures page:
69	//
70	//    https://wiki.wireshark.org/SampleCaptures
71	//    https://wiki.wireshark.org/SampleCaptures?action=AttachFile&do=get&target=bfd-raw-auth-simple.pcap
72	//
73	// Changed to remove the authentication header, and adjust all of the lengths
74	var testPacketBFD = []byte{
75		0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x10, 0x94, 0x00, 0x00, 0x02, 0x08, 0x00, 0x45, 0x00,
76		0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x11, 0x2f, 0x58, 0xc0, 0x55, 0x01, 0x02, 0xc0, 0x00,
77		0x00, 0x01, 0xc0, 0x00, 0x0e, 0xc8, 0x00, 0x20, 0x72, 0x31, 0x20, 0x40, 0x05, 0x18, 0x00, 0x00,
78		0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x42, 0x40, 0x00, 0x0f, 0x42, 0x40, 0x00, 0x00,
79		0x00, 0x00, 0x01, 0x4e, 0x0a, 0x90, 0x40,
80	}
81
82	// Assemble the BFD object that we expect to emerge from this test.
83	pExpectedBFD := &BFD{
84		BaseLayer: BaseLayer{
85			Contents: []byte{
86				0x20, 0x40, 0x05, 0x18, 0x00, 0x00, 0x00, 0x01,
87				0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x42, 0x40,
88				0x00, 0x0f, 0x42, 0x40, 0x00, 0x00, 0x00, 0x00,
89			},
90			Payload: nil,
91		},
92		Version:    1,
93		Diagnostic: BFDDiagnosticNone,
94		State:      BFDStateDown,
95		Poll:       false,
96		Final:      false,
97		ControlPlaneIndependent:   false,
98		AuthPresent:               false,
99		Demand:                    false,
100		Multipoint:                false,
101		DetectMultiplier:          5,
102		MyDiscriminator:           1,
103		YourDiscriminator:         0,
104		DesiredMinTxInterval:      1000000,
105		RequiredMinRxInterval:     1000000,
106		RequiredMinEchoRxInterval: 0,
107		AuthHeader:                nil,
108	}
109
110	checkBFD("testNoAuth", t, testPacketBFD, pExpectedBFD)
111}
112
113//******************************************************************************
114
115func TestBFDAuthTypePassword(t *testing.T) {
116
117	// This test packet is the first BFD packet in the BFD sample capture
118	// pcap file bfd-raw-auth-simple.pcap on the Wireshark sample captures page:
119	//
120	//    https://wiki.wireshark.org/SampleCaptures
121	//    https://wiki.wireshark.org/SampleCaptures?action=AttachFile&do=get&target=bfd-raw-auth-simple.pcap
122	var testPacketBFD = []byte{
123		0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x10, 0x94, 0x00, 0x00, 0x02, 0x08, 0x00, 0x45, 0x00,
124		0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x11, 0x2f, 0x58, 0xc0, 0x55, 0x01, 0x02, 0xc0, 0x00,
125		0x00, 0x01, 0xc0, 0x00, 0x0e, 0xc8, 0x00, 0x29, 0x72, 0x31, 0x20, 0x44, 0x05, 0x21, 0x00, 0x00,
126		0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x42, 0x40, 0x00, 0x0f, 0x42, 0x40, 0x00, 0x00,
127		0x00, 0x00, 0x01, 0x09, 0x02, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4e, 0x0a, 0x90, 0x40,
128	}
129
130	// Assemble the BFD object that we expect to emerge from this test.
131	pExpectedBFD := &BFD{
132		BaseLayer: BaseLayer{
133			Contents: []byte{
134				0x20, 0x44, 0x05, 0x21, 0x00, 0x00, 0x00, 0x01,
135				0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x42, 0x40,
136				0x00, 0x0f, 0x42, 0x40, 0x00, 0x00, 0x00, 0x00,
137				0x01, 0x09, 0x02, 0x73, 0x65, 0x63, 0x72, 0x65,
138				0x74,
139			},
140			Payload: nil,
141		},
142		Version:    1,
143		Diagnostic: BFDDiagnosticNone,
144		State:      BFDStateDown,
145		Poll:       false,
146		Final:      false,
147		ControlPlaneIndependent:   false,
148		AuthPresent:               true,
149		Demand:                    false,
150		Multipoint:                false,
151		DetectMultiplier:          5,
152		MyDiscriminator:           1,
153		YourDiscriminator:         0,
154		DesiredMinTxInterval:      1000000,
155		RequiredMinRxInterval:     1000000,
156		RequiredMinEchoRxInterval: 0,
157		AuthHeader: &BFDAuthHeader{
158			AuthType:       BFDAuthTypePassword,
159			KeyID:          2,
160			SequenceNumber: 0,
161			Data:           []byte{'s', 'e', 'c', 'r', 'e', 't'},
162		},
163	}
164
165	checkBFD("testBFDAuthTypePassword", t, testPacketBFD, pExpectedBFD)
166}
167
168//******************************************************************************
169
170func TestBFDAuthTypeKeyedMD5(t *testing.T) {
171
172	// This test packet is the first BFD packet in the BFD sample capture
173	// pcap file bfd-raw-auth-md5.pcap on the Wireshark sample captures page:
174	//
175	//    https://wiki.wireshark.org/SampleCaptures
176	//    https://wiki.wireshark.org/SampleCaptures?action=AttachFile&do=get&target=bfd-raw-auth-md5.pcap
177	var testPacketBFD = []byte{
178		0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x10, 0x94, 0x00, 0x00, 0x02, 0x08, 0x00, 0x45, 0x00,
179		0x00, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x11, 0x2f, 0x48, 0xc0, 0x55, 0x01, 0x02, 0xc0, 0x00,
180		0x00, 0x01, 0x04, 0x00, 0x0e, 0xc8, 0x00, 0x38, 0x6a, 0xcc, 0x20, 0x44, 0x05, 0x30, 0x00, 0x00,
181		0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x42, 0x40, 0x00, 0x0f, 0x42, 0x40, 0x00, 0x00,
182		0x00, 0x00, 0x02, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
183		0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x3c, 0xc3, 0xf8, 0x21,
184	}
185
186	// Assemble the BFD object that we expect to emerge from this test.
187	pExpectedBFD := &BFD{
188		BaseLayer: BaseLayer{
189			Contents: []byte{
190				0x20, 0x44, 0x05, 0x30, 0x00, 0x00, 0x00, 0x01,
191				0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x42, 0x40,
192				0x00, 0x0f, 0x42, 0x40, 0x00, 0x00, 0x00, 0x00,
193				0x02, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x05,
194				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
195				0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
196			},
197			Payload: nil,
198		},
199		Version:    1,
200		Diagnostic: BFDDiagnosticNone,
201		State:      BFDStateDown,
202		Poll:       false,
203		Final:      false,
204		ControlPlaneIndependent:   false,
205		AuthPresent:               true,
206		Demand:                    false,
207		Multipoint:                false,
208		DetectMultiplier:          5,
209		MyDiscriminator:           1,
210		YourDiscriminator:         0,
211		DesiredMinTxInterval:      1000000,
212		RequiredMinRxInterval:     1000000,
213		RequiredMinEchoRxInterval: 0,
214		AuthHeader: &BFDAuthHeader{
215			AuthType:       BFDAuthTypeKeyedMD5,
216			KeyID:          2,
217			SequenceNumber: 5,
218			Data: []byte{
219				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
220				0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
221			},
222		},
223	}
224
225	checkBFD("testBFDAuthTypeKeyedMD5", t, testPacketBFD, pExpectedBFD)
226}
227
228//******************************************************************************
229
230func TestBFDAuthTypeMeticulousKeyedSHA1(t *testing.T) {
231
232	// This test packet is the first BFD packet in the BFD sample capture
233	// pcap file bfd-raw-auth-sha1.pcap on the Wireshark sample captures page:
234	//
235	//    https://wiki.wireshark.org/SampleCaptures
236	//    https://wiki.wireshark.org/SampleCaptures?action=AttachFile&do=get&target=bfd-raw-auth-sha1.pcap
237	var testPacketBFD = []byte{
238		0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x10, 0x94, 0x00, 0x00, 0x02, 0x08, 0x00, 0x45, 0x00,
239		0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x11, 0x2f, 0x45, 0xc0, 0x55, 0x01, 0x02, 0xc0, 0x00,
240		0x00, 0x01, 0x04, 0x00, 0x0e, 0xc8, 0x00, 0x3c, 0x37, 0x8a, 0x20, 0x44, 0x05, 0x34, 0x00, 0x00,
241		0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x42, 0x40, 0x00, 0x0f, 0x42, 0x40, 0x00, 0x00,
242		0x00, 0x00, 0x05, 0x1c, 0x02, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
243		0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0xea, 0x6d,
244		0x1f, 0x21,
245	}
246
247	// Assemble the BFD object that we expect to emerge from this test.
248	pExpectedBFD := &BFD{
249		BaseLayer: BaseLayer{
250			Contents: []byte{
251				0x20, 0x44, 0x05, 0x34, 0x00, 0x00, 0x00, 0x01,
252				0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x42, 0x40,
253				0x00, 0x0f, 0x42, 0x40, 0x00, 0x00, 0x00, 0x00,
254				0x05, 0x1c, 0x02, 0x00, 0x00, 0x00, 0x00, 0x05,
255				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
256				0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
257				0x17, 0x18, 0x19, 0x1a,
258			},
259			Payload: nil,
260		},
261		Version:    1,
262		Diagnostic: BFDDiagnosticNone,
263		State:      BFDStateDown,
264		Poll:       false,
265		Final:      false,
266		ControlPlaneIndependent:   false,
267		AuthPresent:               true,
268		Demand:                    false,
269		Multipoint:                false,
270		DetectMultiplier:          5,
271		MyDiscriminator:           1,
272		YourDiscriminator:         0,
273		DesiredMinTxInterval:      1000000,
274		RequiredMinRxInterval:     1000000,
275		RequiredMinEchoRxInterval: 0,
276		AuthHeader: &BFDAuthHeader{
277			AuthType:       BFDAuthTypeMeticulousKeyedSHA1,
278			KeyID:          2,
279			SequenceNumber: 5,
280			Data: []byte{
281				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
282				0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
283				0x17, 0x18, 0x19, 0x1a,
284			},
285		},
286	}
287
288	checkBFD("TestBFDAuthTypeMeticulousKeyedSHA1", t, testPacketBFD, pExpectedBFD)
289}
290