github.com/gopacket/gopacket@v1.1.0/layers/bfd.go (about)

     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/gopacket/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  //
   252  //	https://en.wikipedia.org/wiki/Bidirectional_Forwarding_Detection
   253  //	This is the best place to get an overview of BFD.
   254  //
   255  // RFC 5880 "Bidirectional Forwarding Detection (BFD)" (2010)
   256  //
   257  //	https://tools.ietf.org/html/rfc5880
   258  //	This is the original BFD specification.
   259  //
   260  // RFC 5881 "Bidirectional Forwarding Detection (BFD) for IPv4 and IPv6 (Single Hop)" (2010)
   261  //
   262  //	https://tools.ietf.org/html/rfc5881
   263  //	Describes the use of the Bidirectional Forwarding Detection (BFD)
   264  //	protocol over IPv4 and IPv6 for single IP hops.
   265  type BFD struct {
   266  	BaseLayer // Stores the packet bytes and payload bytes.
   267  
   268  	Version                   BFDVersion          // Version of the BFD protocol.
   269  	Diagnostic                BFDDiagnostic       // Diagnostic code for last state change
   270  	State                     BFDState            // Current state
   271  	Poll                      bool                // Requesting verification
   272  	Final                     bool                // Responding to a received BFD Control packet that had the Poll (P) bit set.
   273  	ControlPlaneIndependent   bool                // BFD implementation does not share fate with its control plane
   274  	AuthPresent               bool                // Authentication Section is present and the session is to be authenticated
   275  	Demand                    bool                // Demand mode is active
   276  	Multipoint                bool                // For future point-to-multipoint extensions. Must always be zero
   277  	DetectMultiplier          BFDDetectMultiplier // Detection time multiplier
   278  	MyDiscriminator           BFDDiscriminator    // A unique, nonzero discriminator value
   279  	YourDiscriminator         BFDDiscriminator    // discriminator received from the remote system.
   280  	DesiredMinTxInterval      BFDTimeInterval     // Minimum interval, in microseconds,  the local system would like to use when transmitting BFD Control packets
   281  	RequiredMinRxInterval     BFDTimeInterval     // Minimum interval, in microseconds, between received BFD Control packets that this system is capable of supporting
   282  	RequiredMinEchoRxInterval BFDTimeInterval     // Minimum interval, in microseconds, between received BFD Echo packets that this system is capable of supporting
   283  	AuthHeader                *BFDAuthHeader      // Authentication data, variable length.
   284  }
   285  
   286  // Length returns the data length of a BFD Control message which
   287  // changes based on the presence and type of authentication
   288  // contained in the message
   289  func (d *BFD) Length() int {
   290  	if d.AuthPresent && (d.AuthHeader != nil) {
   291  		return bfdMinimumRecordSizeInBytes + d.AuthHeader.Length()
   292  	}
   293  
   294  	return bfdMinimumRecordSizeInBytes
   295  }
   296  
   297  // LayerType returns the layer type of the BFD object, which is LayerTypeBFD.
   298  func (d *BFD) LayerType() gopacket.LayerType {
   299  	return LayerTypeBFD
   300  }
   301  
   302  // decodeBFD analyses a byte slice and attempts to decode it as a BFD
   303  // control packet
   304  //
   305  // If it succeeds, it loads p with information about the packet and returns nil.
   306  // If it fails, it returns an error (non nil).
   307  //
   308  // This function is employed in layertypes.go to register the BFD layer.
   309  func decodeBFD(data []byte, p gopacket.PacketBuilder) error {
   310  
   311  	// Attempt to decode the byte slice.
   312  	d := &BFD{}
   313  	err := d.DecodeFromBytes(data, p)
   314  	if err != nil {
   315  		return err
   316  	}
   317  
   318  	// If the decoding worked, add the layer to the packet and set it
   319  	// as the application layer too, if there isn't already one.
   320  	p.AddLayer(d)
   321  	p.SetApplicationLayer(d)
   322  
   323  	return nil
   324  }
   325  
   326  // DecodeFromBytes analyses a byte slice and attempts to decode it as a BFD
   327  // control packet.
   328  //
   329  // Upon succeeds, it loads the BFD object with information about the packet
   330  // and returns nil.
   331  // Upon failure, it returns an error (non nil).
   332  func (d *BFD) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   333  
   334  	// If the data block is too short to be a BFD record, then return an error.
   335  	if len(data) < bfdMinimumRecordSizeInBytes {
   336  		df.SetTruncated()
   337  		return errors.New("BFD packet too short")
   338  	}
   339  
   340  	pLen := uint8(data[3])
   341  	if len(data) != int(pLen) {
   342  		return errors.New("BFD packet length does not match")
   343  	}
   344  
   345  	// BFD type embeds type BaseLayer which contains two fields:
   346  	//    Contents is supposed to contain the bytes of the data at this level.
   347  	//    Payload is supposed to contain the payload of this level.
   348  	// Here we set the baselayer to be the bytes of the BFD record.
   349  	d.BaseLayer = BaseLayer{Contents: data[:len(data)]}
   350  
   351  	// Extract the fields from the block of bytes.
   352  	// To make sense of this, refer to the packet diagram
   353  	// above and the section on endian conventions.
   354  
   355  	// The first few fields are all packed into the first 32 bits. Unpack them.
   356  	d.Version = BFDVersion(((data[0] & 0xE0) >> 5))
   357  	d.Diagnostic = BFDDiagnostic(data[0] & 0x1F)
   358  	data = data[1:]
   359  
   360  	d.State = BFDState((data[0] & 0xC0) >> 6)
   361  	d.Poll = data[0]&0x20 != 0
   362  	d.Final = data[0]&0x10 != 0
   363  	d.ControlPlaneIndependent = data[0]&0x08 != 0
   364  	d.AuthPresent = data[0]&0x04 != 0
   365  	d.Demand = data[0]&0x02 != 0
   366  	d.Multipoint = data[0]&0x01 != 0
   367  	data = data[1:]
   368  
   369  	data, d.DetectMultiplier = data[1:], BFDDetectMultiplier(data[0])
   370  	data, _ = data[1:], uint8(data[0]) // Consume length
   371  
   372  	// The remaining fields can just be copied in big endian order.
   373  	data, d.MyDiscriminator = data[4:], BFDDiscriminator(binary.BigEndian.Uint32(data[:4]))
   374  	data, d.YourDiscriminator = data[4:], BFDDiscriminator(binary.BigEndian.Uint32(data[:4]))
   375  	data, d.DesiredMinTxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))
   376  	data, d.RequiredMinRxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))
   377  	data, d.RequiredMinEchoRxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))
   378  
   379  	if d.AuthPresent && (len(data) > 2) {
   380  		d.AuthHeader = &BFDAuthHeader{}
   381  		data, d.AuthHeader.AuthType = data[1:], BFDAuthType(data[0])
   382  		data, _ = data[1:], uint8(data[0]) // Consume length
   383  		data, d.AuthHeader.KeyID = data[1:], BFDAuthKeyID(data[0])
   384  
   385  		switch d.AuthHeader.AuthType {
   386  		case BFDAuthTypePassword:
   387  			d.AuthHeader.Data = BFDAuthData(data)
   388  		case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5:
   389  			// Skipped reserved byte
   390  			data, d.AuthHeader.SequenceNumber = data[5:], BFDAuthSequenceNumber(binary.BigEndian.Uint32(data[1:5]))
   391  			d.AuthHeader.Data = BFDAuthData(data)
   392  		case BFDAuthTypeKeyedSHA1, BFDAuthTypeMeticulousKeyedSHA1:
   393  			// Skipped reserved byte
   394  			data, d.AuthHeader.SequenceNumber = data[5:], BFDAuthSequenceNumber(binary.BigEndian.Uint32(data[1:5]))
   395  			d.AuthHeader.Data = BFDAuthData(data)
   396  		}
   397  	}
   398  
   399  	return nil
   400  }
   401  
   402  // SerializeTo writes the serialized form of this layer into the
   403  // SerializationBuffer, implementing gopacket.SerializableLayer.
   404  // See the docs for gopacket.SerializableLayer for more info.
   405  func (d *BFD) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   406  	data, err := b.PrependBytes(bfdMinimumRecordSizeInBytes)
   407  	if err != nil {
   408  		return err
   409  	}
   410  
   411  	// Pack the first few fields into the first 32 bits.
   412  	data[0] = byte(byte(d.Version<<5) | byte(d.Diagnostic))
   413  	h := uint8(0)
   414  	h |= (uint8(d.State) << 6)
   415  	h |= (uint8(bool2uint8(d.Poll)) << 5)
   416  	h |= (uint8(bool2uint8(d.Final)) << 4)
   417  	h |= (uint8(bool2uint8(d.ControlPlaneIndependent)) << 3)
   418  	h |= (uint8(bool2uint8(d.AuthPresent)) << 2)
   419  	h |= (uint8(bool2uint8(d.Demand)) << 1)
   420  	h |= uint8(bool2uint8(d.Multipoint))
   421  	data[1] = byte(h)
   422  	data[2] = byte(d.DetectMultiplier)
   423  	data[3] = byte(d.Length())
   424  
   425  	// The remaining fields can just be copied in big endian order.
   426  	binary.BigEndian.PutUint32(data[4:], uint32(d.MyDiscriminator))
   427  	binary.BigEndian.PutUint32(data[8:], uint32(d.YourDiscriminator))
   428  	binary.BigEndian.PutUint32(data[12:], uint32(d.DesiredMinTxInterval))
   429  	binary.BigEndian.PutUint32(data[16:], uint32(d.RequiredMinRxInterval))
   430  	binary.BigEndian.PutUint32(data[20:], uint32(d.RequiredMinEchoRxInterval))
   431  
   432  	if d.AuthPresent && (d.AuthHeader != nil) {
   433  		auth, err := b.AppendBytes(int(d.AuthHeader.Length()))
   434  		if err != nil {
   435  			return err
   436  		}
   437  
   438  		auth[0] = byte(d.AuthHeader.AuthType)
   439  		auth[1] = byte(d.AuthHeader.Length())
   440  		auth[2] = byte(d.AuthHeader.KeyID)
   441  
   442  		switch d.AuthHeader.AuthType {
   443  		case BFDAuthTypePassword:
   444  			copy(auth[3:], d.AuthHeader.Data)
   445  		case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5:
   446  			auth[3] = byte(0)
   447  			binary.BigEndian.PutUint32(auth[4:], uint32(d.AuthHeader.SequenceNumber))
   448  			copy(auth[8:], d.AuthHeader.Data)
   449  		case BFDAuthTypeKeyedSHA1, BFDAuthTypeMeticulousKeyedSHA1:
   450  			auth[3] = byte(0)
   451  			binary.BigEndian.PutUint32(auth[4:], uint32(d.AuthHeader.SequenceNumber))
   452  			copy(auth[8:], d.AuthHeader.Data)
   453  		}
   454  	}
   455  
   456  	return nil
   457  }
   458  
   459  // CanDecode returns a set of layers that BFD objects can decode.
   460  // As BFD objects can only decide the BFD layer, we can return just that layer.
   461  // Apparently a single layer type implements LayerClass.
   462  func (d *BFD) CanDecode() gopacket.LayerClass {
   463  	return LayerTypeBFD
   464  }
   465  
   466  // NextLayerType specifies the next layer that GoPacket should attempt to
   467  // analyse after this (BFD) layer. As BFD packets do not contain any payload
   468  // bytes, there are no further layers to analyse.
   469  func (d *BFD) NextLayerType() gopacket.LayerType {
   470  	return gopacket.LayerTypeZero
   471  }
   472  
   473  // Payload returns an empty byte slice as BFD packets do not carry a payload
   474  func (d *BFD) Payload() []byte {
   475  	return nil
   476  }
   477  
   478  // bool2uint8 converts a bool to uint8
   479  func bool2uint8(b bool) uint8 {
   480  	if b {
   481  		return 1
   482  	}
   483  	return 0
   484  }