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 }