Fix unit tests
[govpp.git] / vendor / github.com / google / gopacket / layers / bfd.go
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 package layers
9
10 import (
11         "encoding/binary"
12         "errors"
13
14         "github.com/google/gopacket"
15 )
16
17 // BFD Control Packet Format
18 // -------------------------
19 // The current version of BFD's RFC (RFC 5880) contains the following
20 // diagram for the BFD Control packet format:
21 //
22 //      0                   1                   2                   3
23 //      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
24 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25 //     |Vers |  Diag   |Sta|P|F|C|A|D|M|  Detect Mult  |    Length     |
26 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27 //     |                       My Discriminator                        |
28 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29 //     |                      Your Discriminator                       |
30 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31 //     |                    Desired Min TX Interval                    |
32 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33 //     |                   Required Min RX Interval                    |
34 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 //     |                 Required Min Echo RX Interval                 |
36 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 //
38 //     An optional Authentication Section MAY be present:
39 //
40 //      0                   1                   2                   3
41 //      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
42 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 //     |   Auth Type   |   Auth Len    |    Authentication Data...     |
44 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 //
46 //
47 //     Simple Password Authentication Section Format
48 //     ---------------------------------------------
49 //      0                   1                   2                   3
50 //      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
51 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 //     |   Auth Type   |   Auth Len    |  Auth Key ID  |  Password...  |
53 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 //     |                              ...                              |
55 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 //
57 //
58 //     Keyed MD5 and Meticulous Keyed MD5 Authentication Section Format
59 //     ----------------------------------------------------------------
60 //      0                   1                   2                   3
61 //      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
62 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 //     |   Auth Type   |   Auth Len    |  Auth Key ID  |   Reserved    |
64 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65 //     |                        Sequence Number                        |
66 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
67 //     |                      Auth Key/Digest...                       |
68 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69 //     |                              ...                              |
70 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 //
72 //
73 //     Keyed SHA1 and Meticulous Keyed SHA1 Authentication Section Format
74 //     ------------------------------------------------------------------
75 //      0                   1                   2                   3
76 //      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
77 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
78 //     |   Auth Type   |   Auth Len    |  Auth Key ID  |   Reserved    |
79 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
80 //     |                        Sequence Number                        |
81 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82 //     |                       Auth Key/Hash...                        |
83 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84 //     |                              ...                              |
85 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86 //
87 //     From https://tools.ietf.org/rfc/rfc5880.txt
88 const bfdMinimumRecordSizeInBytes int = 24
89
90 // BFDVersion represents the version as decoded from the BFD control message
91 type BFDVersion uint8
92
93 // BFDDiagnostic represents diagnostic infomation about a BFD session
94 type BFDDiagnostic uint8
95
96 // constants that define BFDDiagnostic flags
97 const (
98         BFDDiagnosticNone               BFDDiagnostic = 0 // No Diagnostic
99         BFDDiagnosticTimeExpired        BFDDiagnostic = 1 // Control Detection Time Expired
100         BFDDiagnosticEchoFailed         BFDDiagnostic = 2 // Echo Function Failed
101         BFDDiagnosticNeighborSignalDown BFDDiagnostic = 3 // Neighbor Signaled Session Down
102         BFDDiagnosticForwardPlaneReset  BFDDiagnostic = 4 // Forwarding Plane Reset
103         BFDDiagnosticPathDown           BFDDiagnostic = 5 // Path Down
104         BFDDiagnosticConcatPathDown     BFDDiagnostic = 6 // Concatenated Path Down
105         BFDDiagnosticAdminDown          BFDDiagnostic = 7 // Administratively Down
106         BFDDiagnosticRevConcatPathDown  BFDDiagnostic = 8 // Reverse Concatenated Path Dow
107 )
108
109 // String returns a string version of BFDDiagnostic
110 func (bd BFDDiagnostic) String() string {
111         switch bd {
112         default:
113                 return "Unknown"
114         case BFDDiagnosticNone:
115                 return "None"
116         case BFDDiagnosticTimeExpired:
117                 return "Control Detection Time Expired"
118         case BFDDiagnosticEchoFailed:
119                 return "Echo Function Failed"
120         case BFDDiagnosticNeighborSignalDown:
121                 return "Neighbor Signaled Session Down"
122         case BFDDiagnosticForwardPlaneReset:
123                 return "Forwarding Plane Reset"
124         case BFDDiagnosticPathDown:
125                 return "Path Down"
126         case BFDDiagnosticConcatPathDown:
127                 return "Concatenated Path Down"
128         case BFDDiagnosticAdminDown:
129                 return "Administratively Down"
130         case BFDDiagnosticRevConcatPathDown:
131                 return "Reverse Concatenated Path Down"
132         }
133 }
134
135 // BFDState represents the state of a BFD session
136 type BFDState uint8
137
138 // constants that define BFDState
139 const (
140         BFDStateAdminDown BFDState = 0
141         BFDStateDown      BFDState = 1
142         BFDStateInit      BFDState = 2
143         BFDStateUp        BFDState = 3
144 )
145
146 // String returns a string version of BFDState
147 func (s BFDState) String() string {
148         switch s {
149         default:
150                 return "Unknown"
151         case BFDStateAdminDown:
152                 return "Admin Down"
153         case BFDStateDown:
154                 return "Down"
155         case BFDStateInit:
156                 return "Init"
157         case BFDStateUp:
158                 return "Up"
159         }
160 }
161
162 // BFDDetectMultiplier represents the negotiated transmit interval,
163 // multiplied by this value, provides the Detection Time for the
164 // receiving system in Asynchronous mode.
165 type BFDDetectMultiplier uint8
166
167 // BFDDiscriminator is a unique, nonzero discriminator value used
168 // to demultiplex multiple BFD sessions between the same pair of systems.
169 type BFDDiscriminator uint32
170
171 // BFDTimeInterval represents a time interval in microseconds
172 type BFDTimeInterval uint32
173
174 // BFDAuthType represents the authentication used in the BFD session
175 type BFDAuthType uint8
176
177 // constants that define the BFDAuthType
178 const (
179         BFDAuthTypeNone                BFDAuthType = 0 // No Auth
180         BFDAuthTypePassword            BFDAuthType = 1 // Simple Password
181         BFDAuthTypeKeyedMD5            BFDAuthType = 2 // Keyed MD5
182         BFDAuthTypeMeticulousKeyedMD5  BFDAuthType = 3 // Meticulous Keyed MD5
183         BFDAuthTypeKeyedSHA1           BFDAuthType = 4 // Keyed SHA1
184         BFDAuthTypeMeticulousKeyedSHA1 BFDAuthType = 5 // Meticulous Keyed SHA1
185 )
186
187 // String returns a string version of BFDAuthType
188 func (at BFDAuthType) String() string {
189         switch at {
190         default:
191                 return "Unknown"
192         case BFDAuthTypeNone:
193                 return "No Authentication"
194         case BFDAuthTypePassword:
195                 return "Simple Password"
196         case BFDAuthTypeKeyedMD5:
197                 return "Keyed MD5"
198         case BFDAuthTypeMeticulousKeyedMD5:
199                 return "Meticulous Keyed MD5"
200         case BFDAuthTypeKeyedSHA1:
201                 return "Keyed SHA1"
202         case BFDAuthTypeMeticulousKeyedSHA1:
203                 return "Meticulous Keyed SHA1"
204         }
205 }
206
207 // BFDAuthKeyID represents the authentication key ID in use for
208 // this packet.  This allows multiple keys to be active simultaneously.
209 type BFDAuthKeyID uint8
210
211 // BFDAuthSequenceNumber represents the sequence number for this packet.
212 // For Keyed Authentication, this value is incremented occasionally.  For
213 // Meticulous Keyed Authentication, this value is incremented for each
214 // successive packet transmitted for a session.  This provides protection
215 // against replay attacks.
216 type BFDAuthSequenceNumber uint32
217
218 // BFDAuthData represents the authentication key or digest
219 type BFDAuthData []byte
220
221 // BFDAuthHeader represents authentication data used in the BFD session
222 type BFDAuthHeader struct {
223         AuthType       BFDAuthType
224         KeyID          BFDAuthKeyID
225         SequenceNumber BFDAuthSequenceNumber
226         Data           BFDAuthData
227 }
228
229 // Length returns the data length of the BFDAuthHeader based on the
230 // authentication type
231 func (h *BFDAuthHeader) Length() int {
232         switch h.AuthType {
233         case BFDAuthTypePassword:
234                 return 3 + len(h.Data)
235         case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5:
236                 return 8 + len(h.Data)
237         case BFDAuthTypeKeyedSHA1, BFDAuthTypeMeticulousKeyedSHA1:
238                 return 8 + len(h.Data)
239         default:
240                 return 0
241         }
242 }
243
244 // BFD represents a BFD control message packet whose payload contains
245 // the control information required to for a BFD session.
246 //
247 // References
248 // ----------
249 //
250 // Wikipedia's BFD entry:
251 //     https://en.wikipedia.org/wiki/Bidirectional_Forwarding_Detection
252 //     This is the best place to get an overview of BFD.
253 //
254 // RFC 5880 "Bidirectional Forwarding Detection (BFD)" (2010)
255 //     https://tools.ietf.org/html/rfc5880
256 //     This is the original BFD specification.
257 //
258 // RFC 5881 "Bidirectional Forwarding Detection (BFD) for IPv4 and IPv6 (Single Hop)" (2010)
259 //     https://tools.ietf.org/html/rfc5881
260 //     Describes the use of the Bidirectional Forwarding Detection (BFD)
261 //     protocol over IPv4 and IPv6 for single IP hops.
262 type BFD struct {
263         BaseLayer // Stores the packet bytes and payload bytes.
264
265         Version                   BFDVersion          // Version of the BFD protocol.
266         Diagnostic                BFDDiagnostic       // Diagnostic code for last state change
267         State                     BFDState            // Current state
268         Poll                      bool                // Requesting verification
269         Final                     bool                // Responding to a received BFD Control packet that had the Poll (P) bit set.
270         ControlPlaneIndependent   bool                // BFD implementation does not share fate with its control plane
271         AuthPresent               bool                // Authentication Section is present and the session is to be authenticated
272         Demand                    bool                // Demand mode is active
273         Multipoint                bool                // For future point-to-multipoint extensions. Must always be zero
274         DetectMultiplier          BFDDetectMultiplier // Detection time multiplier
275         MyDiscriminator           BFDDiscriminator    // A unique, nonzero discriminator value
276         YourDiscriminator         BFDDiscriminator    // discriminator received from the remote system.
277         DesiredMinTxInterval      BFDTimeInterval     // Minimum interval, in microseconds,  the local system would like to use when transmitting BFD Control packets
278         RequiredMinRxInterval     BFDTimeInterval     // Minimum interval, in microseconds, between received BFD Control packets that this system is capable of supporting
279         RequiredMinEchoRxInterval BFDTimeInterval     // Minimum interval, in microseconds, between received BFD Echo packets that this system is capable of supporting
280         AuthHeader                *BFDAuthHeader      // Authentication data, variable length.
281 }
282
283 // Length returns the data length of a BFD Control message which
284 // changes based on the presence and type of authentication
285 // contained in the message
286 func (d *BFD) Length() int {
287         if d.AuthPresent && (d.AuthHeader != nil) {
288                 return bfdMinimumRecordSizeInBytes + d.AuthHeader.Length()
289         }
290
291         return bfdMinimumRecordSizeInBytes
292 }
293
294 // LayerType returns the layer type of the BFD object, which is LayerTypeBFD.
295 func (d *BFD) LayerType() gopacket.LayerType {
296         return LayerTypeBFD
297 }
298
299 // decodeBFD analyses a byte slice and attempts to decode it as a BFD
300 // control packet
301 //
302 // If it succeeds, it loads p with information about the packet and returns nil.
303 // If it fails, it returns an error (non nil).
304 //
305 // This function is employed in layertypes.go to register the BFD layer.
306 func decodeBFD(data []byte, p gopacket.PacketBuilder) error {
307
308         // Attempt to decode the byte slice.
309         d := &BFD{}
310         err := d.DecodeFromBytes(data, p)
311         if err != nil {
312                 return err
313         }
314
315         // If the decoding worked, add the layer to the packet and set it
316         // as the application layer too, if there isn't already one.
317         p.AddLayer(d)
318         p.SetApplicationLayer(d)
319
320         return nil
321 }
322
323 // DecodeFromBytes analyses a byte slice and attempts to decode it as a BFD
324 // control packet.
325 //
326 // Upon succeeds, it loads the BFD object with information about the packet
327 // and returns nil.
328 // Upon failure, it returns an error (non nil).
329 func (d *BFD) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
330
331         // If the data block is too short to be a BFD record, then return an error.
332         if len(data) < bfdMinimumRecordSizeInBytes {
333                 df.SetTruncated()
334                 return errors.New("BFD packet too short")
335         }
336
337         pLen := uint8(data[3])
338         if len(data) != int(pLen) {
339                 return errors.New("BFD packet length does not match")
340         }
341
342         // BFD type embeds type BaseLayer which contains two fields:
343         //    Contents is supposed to contain the bytes of the data at this level.
344         //    Payload is supposed to contain the payload of this level.
345         // Here we set the baselayer to be the bytes of the BFD record.
346         d.BaseLayer = BaseLayer{Contents: data[:len(data)]}
347
348         // Extract the fields from the block of bytes.
349         // To make sense of this, refer to the packet diagram
350         // above and the section on endian conventions.
351
352         // The first few fields are all packed into the first 32 bits. Unpack them.
353         d.Version = BFDVersion(((data[0] & 0xE0) >> 5))
354         d.Diagnostic = BFDDiagnostic(data[0] & 0x1F)
355         data = data[1:]
356
357         d.State = BFDState((data[0] & 0xC0) >> 6)
358         d.Poll = data[0]&0x20 != 0
359         d.Final = data[0]&0x10 != 0
360         d.ControlPlaneIndependent = data[0]&0x08 != 0
361         d.AuthPresent = data[0]&0x04 != 0
362         d.Demand = data[0]&0x02 != 0
363         d.Multipoint = data[0]&0x01 != 0
364         data = data[1:]
365
366         data, d.DetectMultiplier = data[1:], BFDDetectMultiplier(data[0])
367         data, _ = data[1:], uint8(data[0]) // Consume length
368
369         // The remaining fields can just be copied in big endian order.
370         data, d.MyDiscriminator = data[4:], BFDDiscriminator(binary.BigEndian.Uint32(data[:4]))
371         data, d.YourDiscriminator = data[4:], BFDDiscriminator(binary.BigEndian.Uint32(data[:4]))
372         data, d.DesiredMinTxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))
373         data, d.RequiredMinRxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))
374         data, d.RequiredMinEchoRxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))
375
376         if d.AuthPresent && (len(data) > 2) {
377                 d.AuthHeader = &BFDAuthHeader{}
378                 data, d.AuthHeader.AuthType = data[1:], BFDAuthType(data[0])
379                 data, _ = data[1:], uint8(data[0]) // Consume length
380                 data, d.AuthHeader.KeyID = data[1:], BFDAuthKeyID(data[0])
381
382                 switch d.AuthHeader.AuthType {
383                 case BFDAuthTypePassword:
384                         d.AuthHeader.Data = BFDAuthData(data)
385                 case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5:
386                         // Skipped reserved byte
387                         data, d.AuthHeader.SequenceNumber = data[5:], BFDAuthSequenceNumber(binary.BigEndian.Uint32(data[1:5]))
388                         d.AuthHeader.Data = BFDAuthData(data)
389                 case BFDAuthTypeKeyedSHA1, BFDAuthTypeMeticulousKeyedSHA1:
390                         // Skipped reserved byte
391                         data, d.AuthHeader.SequenceNumber = data[5:], BFDAuthSequenceNumber(binary.BigEndian.Uint32(data[1:5]))
392                         d.AuthHeader.Data = BFDAuthData(data)
393                 }
394         }
395
396         return nil
397 }
398
399 // SerializeTo writes the serialized form of this layer into the
400 // SerializationBuffer, implementing gopacket.SerializableLayer.
401 // See the docs for gopacket.SerializableLayer for more info.
402 func (d *BFD) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
403         data, err := b.PrependBytes(bfdMinimumRecordSizeInBytes)
404         if err != nil {
405                 return err
406         }
407
408         // Pack the first few fields into the first 32 bits.
409         data[0] = byte(byte(d.Version<<5) | byte(d.Diagnostic))
410         h := uint8(0)
411         h |= (uint8(d.State) << 6)
412         h |= (uint8(bool2uint8(d.Poll)) << 5)
413         h |= (uint8(bool2uint8(d.Final)) << 4)
414         h |= (uint8(bool2uint8(d.ControlPlaneIndependent)) << 3)
415         h |= (uint8(bool2uint8(d.AuthPresent)) << 2)
416         h |= (uint8(bool2uint8(d.Demand)) << 1)
417         h |= uint8(bool2uint8(d.Multipoint))
418         data[1] = byte(h)
419         data[2] = byte(d.DetectMultiplier)
420         data[3] = byte(d.Length())
421
422         // The remaining fields can just be copied in big endian order.
423         binary.BigEndian.PutUint32(data[4:], uint32(d.MyDiscriminator))
424         binary.BigEndian.PutUint32(data[8:], uint32(d.YourDiscriminator))
425         binary.BigEndian.PutUint32(data[12:], uint32(d.DesiredMinTxInterval))
426         binary.BigEndian.PutUint32(data[16:], uint32(d.RequiredMinRxInterval))
427         binary.BigEndian.PutUint32(data[20:], uint32(d.RequiredMinEchoRxInterval))
428
429         if d.AuthPresent && (d.AuthHeader != nil) {
430                 auth, err := b.AppendBytes(int(d.AuthHeader.Length()))
431                 if err != nil {
432                         return err
433                 }
434
435                 auth[0] = byte(d.AuthHeader.AuthType)
436                 auth[1] = byte(d.AuthHeader.Length())
437                 auth[2] = byte(d.AuthHeader.KeyID)
438
439                 switch d.AuthHeader.AuthType {
440                 case BFDAuthTypePassword:
441                         copy(auth[3:], d.AuthHeader.Data)
442                 case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5:
443                         auth[3] = byte(0)
444                         binary.BigEndian.PutUint32(auth[4:], uint32(d.AuthHeader.SequenceNumber))
445                         copy(auth[8:], d.AuthHeader.Data)
446                 case BFDAuthTypeKeyedSHA1, BFDAuthTypeMeticulousKeyedSHA1:
447                         auth[3] = byte(0)
448                         binary.BigEndian.PutUint32(auth[4:], uint32(d.AuthHeader.SequenceNumber))
449                         copy(auth[8:], d.AuthHeader.Data)
450                 }
451         }
452
453         return nil
454 }
455
456 // CanDecode returns a set of layers that BFD objects can decode.
457 // As BFD objects can only decide the BFD layer, we can return just that layer.
458 // Apparently a single layer type implements LayerClass.
459 func (d *BFD) CanDecode() gopacket.LayerClass {
460         return LayerTypeBFD
461 }
462
463 // NextLayerType specifies the next layer that GoPacket should attempt to
464 // analyse after this (BFD) layer. As BFD packets do not contain any payload
465 // bytes, there are no further layers to analyse.
466 func (d *BFD) NextLayerType() gopacket.LayerType {
467         return gopacket.LayerTypeZero
468 }
469
470 // Payload returns an empty byte slice as BFD packets do not carry a payload
471 func (d *BFD) Payload() []byte {
472         return nil
473 }
474
475 // bool2uint8 converts a bool to uint8
476 func bool2uint8(b bool) uint8 {
477         if b {
478                 return 1
479         }
480         return 0
481 }