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  }