ODPM 266: Go-libmemif + 2 examples.
[govpp.git] / vendor / github.com / google / gopacket / layers / bfd.go
diff --git a/vendor/github.com/google/gopacket/layers/bfd.go b/vendor/github.com/google/gopacket/layers/bfd.go
new file mode 100644 (file)
index 0000000..43030fb
--- /dev/null
@@ -0,0 +1,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
+}