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 7package layers 8 9import ( 10 "encoding/binary" 11 "errors" 12 "fmt" 13 "net" 14 15 "github.com/google/gopacket" 16) 17 18type LinuxSLLPacketType uint16 19 20const ( 21 LinuxSLLPacketTypeHost LinuxSLLPacketType = 0 // To us 22 LinuxSLLPacketTypeBroadcast LinuxSLLPacketType = 1 // To all 23 LinuxSLLPacketTypeMulticast LinuxSLLPacketType = 2 // To group 24 LinuxSLLPacketTypeOtherhost LinuxSLLPacketType = 3 // To someone else 25 LinuxSLLPacketTypeOutgoing LinuxSLLPacketType = 4 // Outgoing of any type 26 // These ones are invisible by user level 27 LinuxSLLPacketTypeLoopback LinuxSLLPacketType = 5 // MC/BRD frame looped back 28 LinuxSLLPacketTypeFastroute LinuxSLLPacketType = 6 // Fastrouted frame 29) 30 31func (l LinuxSLLPacketType) String() string { 32 switch l { 33 case LinuxSLLPacketTypeHost: 34 return "host" 35 case LinuxSLLPacketTypeBroadcast: 36 return "broadcast" 37 case LinuxSLLPacketTypeMulticast: 38 return "multicast" 39 case LinuxSLLPacketTypeOtherhost: 40 return "otherhost" 41 case LinuxSLLPacketTypeOutgoing: 42 return "outgoing" 43 case LinuxSLLPacketTypeLoopback: 44 return "loopback" 45 case LinuxSLLPacketTypeFastroute: 46 return "fastroute" 47 } 48 return fmt.Sprintf("Unknown(%d)", int(l)) 49} 50 51type LinuxSLL struct { 52 BaseLayer 53 PacketType LinuxSLLPacketType 54 AddrLen uint16 55 Addr net.HardwareAddr 56 EthernetType EthernetType 57 AddrType uint16 58} 59 60// LayerType returns LayerTypeLinuxSLL. 61func (sll *LinuxSLL) LayerType() gopacket.LayerType { return LayerTypeLinuxSLL } 62 63func (sll *LinuxSLL) CanDecode() gopacket.LayerClass { 64 return LayerTypeLinuxSLL 65} 66 67func (sll *LinuxSLL) LinkFlow() gopacket.Flow { 68 return gopacket.NewFlow(EndpointMAC, sll.Addr, nil) 69} 70 71func (sll *LinuxSLL) NextLayerType() gopacket.LayerType { 72 return sll.EthernetType.LayerType() 73} 74 75func (sll *LinuxSLL) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 76 if len(data) < 16 { 77 return errors.New("Linux SLL packet too small") 78 } 79 sll.PacketType = LinuxSLLPacketType(binary.BigEndian.Uint16(data[0:2])) 80 sll.AddrType = binary.BigEndian.Uint16(data[2:4]) 81 sll.AddrLen = binary.BigEndian.Uint16(data[4:6]) 82 83 sll.Addr = net.HardwareAddr(data[6 : sll.AddrLen+6]) 84 sll.EthernetType = EthernetType(binary.BigEndian.Uint16(data[14:16])) 85 sll.BaseLayer = BaseLayer{data[:16], data[16:]} 86 87 return nil 88} 89 90func decodeLinuxSLL(data []byte, p gopacket.PacketBuilder) error { 91 sll := &LinuxSLL{} 92 if err := sll.DecodeFromBytes(data, p); err != nil { 93 return err 94 } 95 p.AddLayer(sll) 96 p.SetLinkLayer(sll) 97 return p.NextDecoder(sll.EthernetType) 98} 99