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

     1  // Copyright 2022 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  	"fmt"
    13  	"net"
    14  
    15  	"github.com/gopacket/gopacket"
    16  )
    17  
    18  // The ARPHardwareType contains a Linux ARPHRD_ value for the link-layer device type
    19  type ARPHardwareType uint16
    20  
    21  const (
    22  	ARPHardwareTypeEthernet      ARPHardwareType = 1
    23  	ARPHardwareTypeFRAD          ARPHardwareType = 770
    24  	ARPHardwareTypeLoopback      ARPHardwareType = 772
    25  	ARPHardwareTypeIPGRE         ARPHardwareType = 778
    26  	ARPHardwareTypeDot11Radiotap ARPHardwareType = 803
    27  )
    28  
    29  func (l ARPHardwareType) String() string {
    30  	switch l {
    31  	case ARPHardwareTypeEthernet:
    32  		return "Ethernet"
    33  	case ARPHardwareTypeFRAD:
    34  		return "Frame Relay Access Device"
    35  	case ARPHardwareTypeLoopback:
    36  		return "Loopback device"
    37  	case ARPHardwareTypeIPGRE:
    38  		return "GRE over IP"
    39  	case ARPHardwareTypeDot11Radiotap:
    40  		return "IEEE 802.11 + radiotap header"
    41  	}
    42  
    43  	return fmt.Sprintf("Unknown(%d)", int(l))
    44  }
    45  
    46  // The LinuxSLL2PacketType can contain the same values as LinuxSLLPacketType accept it is a uint8 instread of a uint16
    47  type LinuxSLL2PacketType uint8
    48  
    49  const (
    50  	LinuxSLL2PacketTypeHost      LinuxSLL2PacketType = 0 // To us
    51  	LinuxSLL2PacketTypeBroadcast LinuxSLL2PacketType = 1 // To all
    52  	LinuxSLL2PacketTypeMulticast LinuxSLL2PacketType = 2 // To group
    53  	LinuxSLL2PacketTypeOtherhost LinuxSLL2PacketType = 3 // To someone else
    54  	LinuxSLL2PacketTypeOutgoing  LinuxSLL2PacketType = 4 // Outgoing of any type
    55  	// These ones are invisible by user level
    56  	LinuxSLL2PacketTypeLoopback  LinuxSLL2PacketType = 5 // MC/BRD frame looped back
    57  	LinuxSLL2PacketTypeFastroute LinuxSLL2PacketType = 6 // Fastrouted frame
    58  )
    59  
    60  func (l LinuxSLL2PacketType) String() string {
    61  	switch l {
    62  	case LinuxSLL2PacketTypeHost:
    63  		return "host"
    64  	case LinuxSLL2PacketTypeBroadcast:
    65  		return "broadcast"
    66  	case LinuxSLL2PacketTypeMulticast:
    67  		return "multicast"
    68  	case LinuxSLL2PacketTypeOtherhost:
    69  		return "otherhost"
    70  	case LinuxSLL2PacketTypeOutgoing:
    71  		return "outgoing"
    72  	case LinuxSLL2PacketTypeLoopback:
    73  		return "loopback"
    74  	case LinuxSLL2PacketTypeFastroute:
    75  		return "fastroute"
    76  	}
    77  	return fmt.Sprintf("Unknown(%d)", int(l))
    78  }
    79  
    80  const (
    81  	LinuxSLL2EthernetTypeDot3    EthernetType = 0x0001
    82  	LinuxSLL2EthernetTypeUnknown EthernetType = 0x0003
    83  	LinuxSLL2EthernetTypeLLC     EthernetType = 0x0004
    84  	LinuxSLL2EthernetTypeCAN     EthernetType = 0x000C
    85  )
    86  
    87  // LinuxSLL2 is the second version of the Linux "cooked" capture encapsulation protocol. It is used to encapsulate
    88  // packets within packet capture files, particularly by libpcap/tcpdump when making a packet capture with -i any
    89  // https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL2.html
    90  type LinuxSLL2 struct {
    91  	BaseLayer
    92  	ProtocolType    EthernetType
    93  	InterfaceIndex  uint32
    94  	ARPHardwareType ARPHardwareType
    95  	PacketType      LinuxSLL2PacketType
    96  	AddrLength      uint8
    97  	Addr            net.HardwareAddr
    98  }
    99  
   100  // LayerType returns LayerTypeLinuxSLL.
   101  func (sll *LinuxSLL2) LayerType() gopacket.LayerType { return LayerTypeLinuxSLL2 }
   102  
   103  func (sll *LinuxSLL2) CanDecode() gopacket.LayerClass {
   104  	return LayerTypeLinuxSLL2
   105  }
   106  
   107  func (sll *LinuxSLL2) LinkFlow() gopacket.Flow {
   108  	return gopacket.NewFlow(EndpointMAC, sll.Addr, nil)
   109  }
   110  
   111  func (sll *LinuxSLL2) NextLayerType() gopacket.LayerType {
   112  	switch sll.ARPHardwareType {
   113  	case ARPHardwareTypeFRAD:
   114  		// If the ARPHRD_ type is ARPHRD_FRAD (770), the protocol type field is ignored,
   115  		// and the payload following the LINKTYPE_LINUX_SLL header is a Frame Relay LAPF frame,
   116  		// beginning with a ITU-T Recommendation Q.922 LAPF header starting with the address field,
   117  		// and without an FCS at the end of the frame.
   118  		return gopacket.LayerTypeZero // LAPF layer not yet implemented
   119  
   120  	case ARPHardwareTypeDot11Radiotap:
   121  		return LayerTypeRadioTap
   122  
   123  	case ARPHardwareTypeIPGRE:
   124  		// Docs: If the ARPHRD_ type is ARPHRD_IPGRE (778), the protocol type field contains a GRE protocol type.
   125  		//
   126  		// It doesn't clearly state if if the next header should be GRE or Ethernet in this case. Will assume ethernet
   127  		// for now
   128  		return LayerTypeEthernet
   129  
   130  	default:
   131  		switch sll.ProtocolType {
   132  		case LinuxSLL2EthernetTypeDot3:
   133  			// Docs: if the frame is a Novell 802.3 frame without an 802.2 LLC header
   134  			return gopacket.LayerTypeZero // Novell 802.3 frame layer not yet implemented
   135  
   136  		case LinuxSLL2EthernetTypeUnknown:
   137  			// Docs: in some mysterious cases;
   138  			return gopacket.LayerTypeZero // Mysterious cases not implemented
   139  
   140  		case LinuxSLL2EthernetTypeLLC:
   141  			return LayerTypeLLC
   142  
   143  		case LinuxSLL2EthernetTypeCAN:
   144  			// Docs: if the frame is a CAN bus frame that begins with a header of the form
   145  			return gopacket.LayerTypeZero
   146  		}
   147  
   148  		return sll.ProtocolType.LayerType()
   149  	}
   150  }
   151  
   152  func (sll *LinuxSLL2) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   153  	if len(data) < 20 {
   154  		return errors.New("Linux SLL2 packet too small")
   155  	}
   156  	sll.ProtocolType = EthernetType(binary.BigEndian.Uint16(data[0:2]))
   157  	sll.InterfaceIndex = binary.BigEndian.Uint32(data[4:8])
   158  	sll.ARPHardwareType = ARPHardwareType(binary.BigEndian.Uint16(data[8:10]))
   159  	sll.PacketType = LinuxSLL2PacketType(data[10])
   160  	sll.AddrLength = data[11]
   161  	sll.Addr = data[12:20]
   162  	sll.Addr = sll.Addr[:sll.AddrLength]
   163  	sll.BaseLayer = BaseLayer{data[:20], data[20:]}
   164  
   165  	return nil
   166  }
   167  
   168  func decodeLinuxSLL2(data []byte, p gopacket.PacketBuilder) error {
   169  	sll := &LinuxSLL2{}
   170  	if err := sll.DecodeFromBytes(data, p); err != nil {
   171  		return err
   172  	}
   173  	p.AddLayer(sll)
   174  	p.SetLinkLayer(sll)
   175  	return p.NextDecoder(sll.NextLayerType())
   176  }