aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/google/gopacket/layers/bfd.go
blob: 43030fb6a557d3a37b9b40bb257bc28aac7e3f6d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
// Copyright 2017 Google, Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree.
//

package layers

import (
	"encoding/binary"
	"errors"

	"github.com/google/gopacket"
)

// BFD Control Packet Format
// -------------------------
// The current version of BFD's RFC (RFC 5880) contains the following
// diagram for the BFD Control packet format:
//
//      0                   1                   2                   3
//      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |Vers |  Diag   |Sta|P|F|C|A|D|M|  Detect Mult  |    Length     |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |                       My Discriminator                        |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |                      Your Discriminator                       |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |                    Desired Min TX Interval                    |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |                   Required Min RX Interval                    |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |                 Required Min Echo RX Interval                 |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
//     An optional Authentication Section MAY be present:
//
//      0                   1                   2                   3
//      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |   Auth Type   |   Auth Len    |    Authentication Data...     |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
//
//     Simple Password Authentication Section Format
//     ---------------------------------------------
//      0                   1                   2                   3
//      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |   Auth Type   |   Auth Len    |  Auth Key ID  |  Password...  |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |                              ...                              |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
//
//     Keyed MD5 and Meticulous Keyed MD5 Authentication Section Format
//     ----------------------------------------------------------------
//      0                   1                   2                   3
//      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |   Auth Type   |   Auth Len    |  Auth Key ID  |   Reserved    |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |                        Sequence Number                        |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |                      Auth Key/Digest...                       |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |                              ...                              |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
//
//     Keyed SHA1 and Meticulous Keyed SHA1 Authentication Section Format
//     ------------------------------------------------------------------
//      0                   1                   2                   3
//      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |   Auth Type   |   Auth Len    |  Auth Key ID  |   Reserved    |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |                        Sequence Number                        |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |                       Auth Key/Hash...                        |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//     |                              ...                              |
//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
//     From https://tools.ietf.org/rfc/rfc5880.txt
const bfdMinimumRecordSizeInBytes int = 24

// BFDVersion represents the version as decoded from the BFD control message
type BFDVersion uint8

// BFDDiagnostic represents diagnostic infomation about a BFD session
type BFDDiagnostic uint8

// constants that define BFDDiagnostic flags
const (
	BFDDiagnosticNone               BFDDiagnostic = 0 // No Diagnostic
	BFDDiagnosticTimeExpired        BFDDiagnostic = 1 // Control Detection Time Expired
	BFDDiagnosticEchoFailed         BFDDiagnostic = 2 // Echo Function Failed
	BFDDiagnosticNeighborSignalDown BFDDiagnostic = 3 // Neighbor Signaled Session Down
	BFDDiagnosticForwardPlaneReset  BFDDiagnostic = 4 // Forwarding Plane Reset
	BFDDiagnosticPathDown           BFDDiagnostic = 5 // Path Down
	BFDDiagnosticConcatPathDown     BFDDiagnostic = 6 // Concatenated Path Down
	BFDDiagnosticAdminDown          BFDDiagnostic = 7 // Administratively Down
	BFDDiagnosticRevConcatPathDown  BFDDiagnostic = 8 // Reverse Concatenated Path Dow
)

// String returns a string version of BFDDiagnostic
func (bd BFDDiagnostic) String() string {
	switch bd {
	default:
		return "Unknown"
	case BFDDiagnosticNone:
		return "None"
	case BFDDiagnosticTimeExpired:
		return "Control Detection Time Expired"
	case BFDDiagnosticEchoFailed:
		return "Echo Function Failed"
	case BFDDiagnosticNeighborSignalDown:
		return "Neighbor Signaled Session Down"
	case BFDDiagnosticForwardPlaneReset:
		return "Forwarding Plane Reset"
	case BFDDiagnosticPathDown:
		return "Path Down"
	case BFDDiagnosticConcatPathDown:
		return "Concatenated Path Down"
	case BFDDiagnosticAdminDown:
		return "Administratively Down"
	case BFDDiagnosticRevConcatPathDown:
		return "Reverse Concatenated Path Down"
	}
}

// BFDState represents the state of a BFD session
type BFDState uint8

// constants that define BFDState
const (
	BFDStateAdminDown BFDState = 0
	BFDStateDown      BFDState = 1
	BFDStateInit      BFDState = 2
	BFDStateUp        BFDState = 3
)

// String returns a string version of BFDState
func (s BFDState) String() string {
	switch s {
	default:
		return "Unknown"
	case BFDStateAdminDown:
		return "Admin Down"
	case BFDStateDown:
		return "Down"
	case BFDStateInit:
		return "Init"
	case BFDStateUp:
		return "Up"
	}
}

// BFDDetectMultiplier represents the negotiated transmit interval,
// multiplied by this value, provides the Detection Time for the
// receiving system in Asynchronous mode.
type BFDDetectMultiplier uint8

// BFDDiscriminator is a unique, nonzero discriminator value used
// to demultiplex multiple BFD sessions between the same pair of systems.
type BFDDiscriminator uint32

// BFDTimeInterval represents a time interval in microseconds
type BFDTimeInterval uint32

// BFDAuthType represents the authentication used in the BFD session
type BFDAuthType uint8

// constants that define the BFDAuthType
const (
	BFDAuthTypeNone                BFDAuthType = 0 // No Auth
	BFDAuthTypePassword            BFDAuthType = 1 // Simple Password
	BFDAuthTypeKeyedMD5            BFDAuthType = 2 // Keyed MD5
	BFDAuthTypeMeticulousKeyedMD5  BFDAuthType = 3 // Meticulous Keyed MD5
	BFDAuthTypeKeyedSHA1           BFDAuthType = 4 // Keyed SHA1
	BFDAuthTypeMeticulousKeyedSHA1 BFDAuthType = 5 // Meticulous Keyed SHA1
)

// String returns a string version of BFDAuthType
func (at BFDAuthType) String() string {
	switch at {
	default:
		return "Unknown"
	case BFDAuthTypeNone:
		return "No Authentication"
	case BFDAuthTypePassword:
		return "Simple Password"
	case BFDAuthTypeKeyedMD5:
		return "Keyed MD5"
	case BFDAuthTypeMeticulousKeyedMD5:
		return "Meticulous Keyed MD5"
	case BFDAuthTypeKeyedSHA1:
		return "Keyed SHA1"
	case BFDAuthTypeMeticulousKeyedSHA1:
		return "Meticulous Keyed SHA1"
	}
}

// BFDAuthKeyID represents the authentication key ID in use for
// this packet.  This allows multiple keys to be active simultaneously.
type BFDAuthKeyID uint8

// BFDAuthSequenceNumber represents the sequence number for this packet.
// For Keyed Authentication, this value is incremented occasionally.  For
// Meticulous Keyed Authentication, this value is incremented for each
// successive packet transmitted for a session.  This provides protection
// against replay attacks.
type BFDAuthSequenceNumber uint32

// BFDAuthData represents the authentication key or digest
type BFDAuthData []byte

// BFDAuthHeader represents authentication data used in the BFD session
type BFDAuthHeader struct {
	AuthType       BFDAuthType
	KeyID          BFDAuthKeyID
	SequenceNumber BFDAuthSequenceNumber
	Data           BFDAuthData
}

// Length returns the data length of the BFDAuthHeader based on the
// authentication type
func (h *BFDAuthHeader) Length() int {
	switch h.AuthType {
	case BFDAuthTypePassword:
		return 3 + len(h.Data)
	case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5:
		return 8 + len(h.Data)
	case BFDAuthTypeKeyedSHA1, BFDAuthTypeMeticulousKeyedSHA1:
		return 8 + len(h.Data)
	default:
		return 0
	}
}

// BFD represents a BFD control message packet whose payload contains
// the control information required to for a BFD session.
//
// References
// ----------
//
// Wikipedia's BFD entry:
//     https://en.wikipedia.org/wiki/Bidirectional_Forwarding_Detection
//     This is the best place to get an overview of BFD.
//
// RFC 5880 "Bidirectional Forwarding Detection (BFD)" (2010)
//     https://tools.ietf.org/html/rfc5880
//     This is the original BFD specification.
//
// RFC 5881 "Bidirectional Forwarding Detection (BFD) for IPv4 and IPv6 (Single Hop)" (2010)
//     https://tools.ietf.org/html/rfc5881
//     Describes the use of the Bidirectional Forwarding Detection (BFD)
//     protocol over IPv4 and IPv6 for single IP hops.
type BFD struct {
	BaseLayer // Stores the packet bytes and payload bytes.

	Version                   BFDVersion          // Version of the BFD protocol.
	Diagnostic                BFDDiagnostic       // Diagnostic code for last state change
	State                     BFDState            // Current state
	Poll                      bool                // Requesting verification
	Final                     bool                // Responding to a received BFD Control packet that had the Poll (P) bit set.
	ControlPlaneIndependent   bool                // BFD implementation does not share fate with its control plane
	AuthPresent               bool                // Authentication Section is present and the session is to be authenticated
	Demand                    bool                // Demand mode is active
	Multipoint                bool                // For future point-to-multipoint extensions. Must always be zero
	DetectMultiplier          BFDDetectMultiplier // Detection time multiplier
	MyDiscriminator           BFDDiscriminator    // A unique, nonzero discriminator value
	YourDiscriminator         BFDDiscriminator    // discriminator received from the remote system.
	DesiredMinTxInterval      BFDTimeInterval     // Minimum interval, in microseconds,  the local system would like to use when transmitting BFD Control packets
	RequiredMinRxInterval     BFDTimeInterval     // Minimum interval, in microseconds, between received BFD Control packets that this system is capable of supporting
	RequiredMinEchoRxInterval BFDTimeInterval     // Minimum interval, in microseconds, between received BFD Echo packets that this system is capable of supporting
	AuthHeader                *BFDAuthHeader      // Authentication data, variable length.
}

// Length returns the data length of a BFD Control message which
// changes based on the presence and type of authentication
// contained in the message
func (d *BFD) Length() int {
	if d.AuthPresent && (d.AuthHeader != nil) {
		return bfdMinimumRecordSizeInBytes + d.AuthHeader.Length()
	}

	return bfdMinimumRecordSizeInBytes
}

// LayerType returns the layer type of the BFD object, which is LayerTypeBFD.
func (d *BFD) LayerType() gopacket.LayerType {
	return LayerTypeBFD
}

// decodeBFD analyses a byte slice and attempts to decode it as a BFD
// control packet
//
// If it succeeds, it loads p with information about the packet and returns nil.
// If it fails, it returns an error (non nil).
//
// This function is employed in layertypes.go to register the BFD layer.
func decodeBFD(data []byte, p gopacket.PacketBuilder) error {

	// Attempt to decode the byte slice.
	d := &BFD{}
	err := d.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}

	// If the decoding worked, add the layer to the packet and set it
	// as the application layer too, if there isn't already one.
	p.AddLayer(d)
	p.SetApplicationLayer(d)

	return nil
}

// DecodeFromBytes analyses a byte slice and attempts to decode it as a BFD
// control packet.
//
// Upon succeeds, it loads the BFD object with information about the packet
// and returns nil.
// Upon failure, it returns an error (non nil).
func (d *BFD) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {

	// If the data block is too short to be a BFD record, then return an error.
	if len(data) < bfdMinimumRecordSizeInBytes {
		df.SetTruncated()
		return errors.New("BFD packet too short")
	}

	pLen := uint8(data[3])
	if len(data) != int(pLen) {
		return errors.New("BFD packet length does not match")
	}

	// BFD type embeds type BaseLayer which contains two fields:
	//    Contents is supposed to contain the bytes of the data at this level.
	//    Payload is supposed to contain the payload of this level.
	// Here we set the baselayer to be the bytes of the BFD record.
	d.BaseLayer = BaseLayer{Contents: data[:len(data)]}

	// Extract the fields from the block of bytes.
	// To make sense of this, refer to the packet diagram
	// above and the section on endian conventions.

	// The first few fields are all packed into the first 32 bits. Unpack them.
	d.Version = BFDVersion(((data[0] & 0xE0) >> 5))
	d.Diagnostic = BFDDiagnostic(data[0] & 0x1F)
	data = data[1:]

	d.State = BFDState((data[0] & 0xC0) >> 6)
	d.Poll = data[0]&0x20 != 0
	d.Final = data[0]&0x10 != 0
	d.ControlPlaneIndependent = data[0]&0x08 != 0
	d.AuthPresent = data[0]&0x04 != 0
	d.Demand = data[0]&0x02 != 0
	d.Multipoint = data[0]&0x01 != 0
	data = data[1:]

	data, d.DetectMultiplier = data[1:], BFDDetectMultiplier(data[0])
	data, _ = data[1:], uint8(data[0]) // Consume length

	// The remaining fields can just be copied in big endian order.
	data, d.MyDiscriminator = data[4:], BFDDiscriminator(binary.BigEndian.Uint32(data[:4]))
	data, d.YourDiscriminator = data[4:], BFDDiscriminator(binary.BigEndian.Uint32(data[:4]))
	data, d.DesiredMinTxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))
	data, d.RequiredMinRxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))
	data, d.RequiredMinEchoRxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))

	if d.AuthPresent && (len(data) > 2) {
		d.AuthHeader = &BFDAuthHeader{}
		data, d.AuthHeader.AuthType = data[1:], BFDAuthType(data[0])
		data, _ = data[1:], uint8(data[0]) // Consume length
		data, d.AuthHeader.KeyID = data[1:], BFDAuthKeyID(data[0])

		switch d.AuthHeader.AuthType {
		case BFDAuthTypePassword:
			d.AuthHeader.Data = BFDAuthData(data)
		case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5:
			// Skipped reserved byte
			data, d.AuthHeader.SequenceNumber = data[5:], BFDAuthSequenceNumber(binary.BigEndian.Uint32(data[1:5]))
			d.AuthHeader.Data = BFDAuthData(data)
		case BFDAuthTypeKeyedSHA1, BFDAuthTypeMeticulousKeyedSHA1:
			// Skipped reserved byte
			data, d.AuthHeader.SequenceNumber = data[5:], BFDAuthSequenceNumber(binary.BigEndian.Uint32(data[1:5]))
			d.AuthHeader.Data = BFDAuthData(data)
		}
	}

	return nil
}

// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (d *BFD) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	data, err := b.PrependBytes(bfdMinimumRecordSizeInBytes)
	if err != nil {
		return err
	}

	// Pack the first few fields into the first 32 bits.
	data[0] = byte(byte(d.Version<<5) | byte(d.Diagnostic))
	h := uint8(0)
	h |= (uint8(d.State) << 6)
	h |= (uint8(bool2uint8(d.Poll)) << 5)
	h |= (uint8(bool2uint8(d.Final)) << 4)
	h |= (uint8(bool2uint8(d.ControlPlaneIndependent)) << 3)
	h |= (uint8(bool2uint8(d.AuthPresent)) << 2)
	h |= (uint8(bool2uint8(d.Demand)) << 1)
	h |= uint8(bool2uint8(d.Multipoint))
	data[1] = byte(h)
	data[2] = byte(d.DetectMultiplier)
	data[3] = byte(d.Length())

	// The remaining fields can just be copied in big endian order.
	binary.BigEndian.PutUint32(data[4:], uint32(d.MyDiscriminator))
	binary.BigEndian.PutUint32(data[8:], uint32(d.YourDiscriminator))
	binary.BigEndian.PutUint32(data[12:], uint32(d.DesiredMinTxInterval))
	binary.BigEndian.PutUint32(data[16:], uint32(d.RequiredMinRxInterval))
	binary.BigEndian.PutUint32(data[20:], uint32(d.RequiredMinEchoRxInterval))

	if d.AuthPresent && (d.AuthHeader != nil) {
		auth, err := b.AppendBytes(int(d.AuthHeader.Length()))
		if err != nil {
			return err
		}

		auth[0] = byte(d.AuthHeader.AuthType)
		auth[1] = byte(d.AuthHeader.Length())
		auth[2] = byte(d.AuthHeader.KeyID)

		switch d.AuthHeader.AuthType {
		case BFDAuthTypePassword:
			copy(auth[3:], d.AuthHeader.Data)
		case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5:
			auth[3] = byte(0)
			binary.BigEndian.PutUint32(auth[4:], uint32(d.AuthHeader.SequenceNumber))
			copy(auth[8:], d.AuthHeader.Data)
		case BFDAuthTypeKeyedSHA1, BFDAuthTypeMeticulousKeyedSHA1:
			auth[3] = byte(0)
			binary.BigEndian.PutUint32(auth[4:], uint32(d.AuthHeader.SequenceNumber))
			copy(auth[8:], d.AuthHeader.Data)
		}
	}

	return nil
}

// CanDecode returns a set of layers that BFD objects can decode.
// As BFD objects can only decide the BFD layer, we can return just that layer.
// Apparently a single layer type implements LayerClass.
func (d *BFD) CanDecode() gopacket.LayerClass {
	return LayerTypeBFD
}

// NextLayerType specifies the next layer that GoPacket should attempt to
// analyse after this (BFD) layer. As BFD packets do not contain any payload
// bytes, there are no further layers to analyse.
func (d *BFD) NextLayerType() gopacket.LayerType {
	return gopacket.LayerTypeZero
}

// Payload returns an empty byte slice as BFD packets do not carry a payload
func (d *BFD) Payload() []byte {
	return nil
}

// bool2uint8 converts a bool to uint8
func bool2uint8(b bool) uint8 {
	if b {
		return 1
	}
	return 0
}