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