github.com/gopacket/gopacket@v1.1.0/layers/ethernet.go (about) 1 // Copyright 2012 Google, Inc. All rights reserved. 2 // Copyright 2009-2011 Andreas Krennmair. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style license 5 // that can be found in the LICENSE file in the root of the source 6 // tree. 7 8 package layers 9 10 import ( 11 "encoding/binary" 12 "errors" 13 "fmt" 14 "net" 15 16 "github.com/gopacket/gopacket" 17 ) 18 19 // EthernetBroadcast is the broadcast MAC address used by Ethernet. 20 var EthernetBroadcast = net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 21 22 // Ethernet is the layer for Ethernet frame headers. 23 type Ethernet struct { 24 BaseLayer 25 SrcMAC, DstMAC net.HardwareAddr 26 EthernetType EthernetType 27 // Length is only set if a length field exists within this header. Ethernet 28 // headers follow two different standards, one that uses an EthernetType, the 29 // other which defines a length the follows with a LLC header (802.3). If the 30 // former is the case, we set EthernetType and Length stays 0. In the latter 31 // case, we set Length and EthernetType = EthernetTypeLLC. 32 Length uint16 33 } 34 35 // LayerType returns LayerTypeEthernet 36 func (e *Ethernet) LayerType() gopacket.LayerType { return LayerTypeEthernet } 37 38 func (e *Ethernet) LinkFlow() gopacket.Flow { 39 return gopacket.NewFlow(EndpointMAC, e.SrcMAC, e.DstMAC) 40 } 41 42 func (eth *Ethernet) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 43 if len(data) < 14 { 44 return errors.New("Ethernet packet too small") 45 } 46 eth.DstMAC = net.HardwareAddr(data[0:6]) 47 eth.SrcMAC = net.HardwareAddr(data[6:12]) 48 eth.EthernetType = EthernetType(binary.BigEndian.Uint16(data[12:14])) 49 eth.BaseLayer = BaseLayer{data[:14], data[14:]} 50 eth.Length = 0 51 if eth.EthernetType < 0x0600 { 52 eth.Length = uint16(eth.EthernetType) 53 eth.EthernetType = EthernetTypeLLC 54 if cmp := len(eth.Payload) - int(eth.Length); cmp < 0 { 55 df.SetTruncated() 56 } else if cmp > 0 { 57 // Strip off bytes at the end, since we have too many bytes 58 eth.Payload = eth.Payload[:len(eth.Payload)-cmp] 59 } 60 // fmt.Println(eth) 61 } 62 return nil 63 } 64 65 // SerializeTo writes the serialized form of this layer into the 66 // SerializationBuffer, implementing gopacket.SerializableLayer. 67 // See the docs for gopacket.SerializableLayer for more info. 68 func (eth *Ethernet) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 69 if len(eth.DstMAC) != 6 { 70 return fmt.Errorf("invalid dst MAC: %v", eth.DstMAC) 71 } 72 if len(eth.SrcMAC) != 6 { 73 return fmt.Errorf("invalid src MAC: %v", eth.SrcMAC) 74 } 75 payload := b.Bytes() 76 bytes, err := b.PrependBytes(14) 77 if err != nil { 78 return err 79 } 80 copy(bytes, eth.DstMAC) 81 copy(bytes[6:], eth.SrcMAC) 82 if eth.Length != 0 || eth.EthernetType == EthernetTypeLLC { 83 if opts.FixLengths { 84 eth.Length = uint16(len(payload)) 85 } 86 if eth.EthernetType != EthernetTypeLLC { 87 return fmt.Errorf("ethernet type %v not compatible with length value %v", eth.EthernetType, eth.Length) 88 } else if eth.Length > 0x0600 { 89 return fmt.Errorf("invalid ethernet length %v", eth.Length) 90 } 91 binary.BigEndian.PutUint16(bytes[12:], eth.Length) 92 } else { 93 binary.BigEndian.PutUint16(bytes[12:], uint16(eth.EthernetType)) 94 } 95 length := len(b.Bytes()) 96 if length < 60 { 97 // Pad out to 60 bytes. 98 padding, err := b.AppendBytes(60 - length) 99 if err != nil { 100 return err 101 } 102 copy(padding, lotsOfZeros[:]) 103 } 104 return nil 105 } 106 107 func (eth *Ethernet) CanDecode() gopacket.LayerClass { 108 return LayerTypeEthernet 109 } 110 111 func (eth *Ethernet) NextLayerType() gopacket.LayerType { 112 return eth.EthernetType.LayerType() 113 } 114 115 func decodeEthernet(data []byte, p gopacket.PacketBuilder) error { 116 eth := &Ethernet{} 117 err := eth.DecodeFromBytes(data, p) 118 if err != nil { 119 return err 120 } 121 p.AddLayer(eth) 122 p.SetLinkLayer(eth) 123 return p.NextDecoder(eth.EthernetType) 124 }