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

     1  // Copyright 2012 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  package layers
     8  
     9  import (
    10  	"encoding/binary"
    11  	"errors"
    12  
    13  	"github.com/gopacket/gopacket"
    14  )
    15  
    16  // MPLS is the MPLS packet header.
    17  type MPLS struct {
    18  	BaseLayer
    19  	Label        uint32
    20  	TrafficClass uint8
    21  	StackBottom  bool
    22  	TTL          uint8
    23  }
    24  
    25  // LayerType returns gopacket.LayerTypeMPLS.
    26  func (m *MPLS) LayerType() gopacket.LayerType { return LayerTypeMPLS }
    27  
    28  // ProtocolGuessingDecoder attempts to guess the protocol of the bytes it's
    29  // given, then decode the packet accordingly.  Its algorithm for guessing is:
    30  //
    31  //	If the packet starts with byte 0x45-0x4F: IPv4
    32  //	If the packet starts with byte 0x60-0x6F: IPv6
    33  //	Otherwise:  Error
    34  //
    35  // See draft-hsmit-isis-aal5mux-00.txt for more detail on this approach.
    36  type ProtocolGuessingDecoder struct{}
    37  
    38  func (ProtocolGuessingDecoder) Decode(data []byte, p gopacket.PacketBuilder) error {
    39  	switch data[0] {
    40  	// 0x40 | header_len, where header_len is at least 5.
    41  	case 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f:
    42  		return decodeIPv4(data, p)
    43  		// IPv6 can start with any byte whose first 4 bits are 0x6.
    44  	case 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f:
    45  		return decodeIPv6(data, p)
    46  	}
    47  	return errors.New("Unable to guess protocol of packet data")
    48  }
    49  
    50  // MPLSPayloadDecoder is the decoder used to data encapsulated by each MPLS
    51  // layer.  MPLS contains no type information, so we have to explicitly decide
    52  // which decoder to use.  This is initially set to ProtocolGuessingDecoder, our
    53  // simple attempt at guessing protocols based on the first few bytes of data
    54  // available to us.  However, if you know that in your environment MPLS always
    55  // encapsulates a specific protocol, you may reset this.
    56  var MPLSPayloadDecoder gopacket.Decoder = ProtocolGuessingDecoder{}
    57  
    58  func decodeMPLS(data []byte, p gopacket.PacketBuilder) error {
    59  	decoded := binary.BigEndian.Uint32(data[:4])
    60  	mpls := &MPLS{
    61  		Label:        decoded >> 12,
    62  		TrafficClass: uint8(decoded>>9) & 0x7,
    63  		StackBottom:  decoded&0x100 != 0,
    64  		TTL:          uint8(decoded),
    65  		BaseLayer:    BaseLayer{data[:4], data[4:]},
    66  	}
    67  	p.AddLayer(mpls)
    68  	if mpls.StackBottom {
    69  		return p.NextDecoder(MPLSPayloadDecoder)
    70  	}
    71  	return p.NextDecoder(gopacket.DecodeFunc(decodeMPLS))
    72  }
    73  
    74  // SerializeTo writes the serialized form of this layer into the
    75  // SerializationBuffer, implementing gopacket.SerializableLayer.
    76  // See the docs for gopacket.SerializableLayer for more info.
    77  func (m *MPLS) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
    78  	bytes, err := b.PrependBytes(4)
    79  	if err != nil {
    80  		return err
    81  	}
    82  	encoded := m.Label << 12
    83  	encoded |= uint32(m.TrafficClass) << 9
    84  	encoded |= uint32(m.TTL)
    85  	if m.StackBottom {
    86  		encoded |= 0x100
    87  	}
    88  	binary.BigEndian.PutUint32(bytes, encoded)
    89  	return nil
    90  }