github.com/gopacket/gopacket@v1.1.0/layers/arp.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  
    15  	"github.com/gopacket/gopacket"
    16  )
    17  
    18  // Potential values for ARP.Operation.
    19  const (
    20  	ARPRequest = 1
    21  	ARPReply   = 2
    22  )
    23  
    24  // ARP is a ARP packet header.
    25  type ARP struct {
    26  	BaseLayer
    27  	AddrType          LinkType
    28  	Protocol          EthernetType
    29  	HwAddressSize     uint8
    30  	ProtAddressSize   uint8
    31  	Operation         uint16
    32  	SourceHwAddress   []byte
    33  	SourceProtAddress []byte
    34  	DstHwAddress      []byte
    35  	DstProtAddress    []byte
    36  }
    37  
    38  // LayerType returns LayerTypeARP
    39  func (arp *ARP) LayerType() gopacket.LayerType { return LayerTypeARP }
    40  
    41  // DecodeFromBytes decodes the given bytes into this layer.
    42  func (arp *ARP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
    43  	if len(data) < 8 {
    44  		df.SetTruncated()
    45  		return fmt.Errorf("ARP length %d too short", len(data))
    46  	}
    47  	arp.AddrType = LinkType(binary.BigEndian.Uint16(data[0:2]))
    48  	arp.Protocol = EthernetType(binary.BigEndian.Uint16(data[2:4]))
    49  	arp.HwAddressSize = data[4]
    50  	arp.ProtAddressSize = data[5]
    51  	arp.Operation = binary.BigEndian.Uint16(data[6:8])
    52  	arpLength := 8 + 2*arp.HwAddressSize + 2*arp.ProtAddressSize
    53  	if len(data) < int(arpLength) {
    54  		df.SetTruncated()
    55  		return fmt.Errorf("ARP length %d too short, %d expected", len(data), arpLength)
    56  	}
    57  	arp.SourceHwAddress = data[8 : 8+arp.HwAddressSize]
    58  	arp.SourceProtAddress = data[8+arp.HwAddressSize : 8+arp.HwAddressSize+arp.ProtAddressSize]
    59  	arp.DstHwAddress = data[8+arp.HwAddressSize+arp.ProtAddressSize : 8+2*arp.HwAddressSize+arp.ProtAddressSize]
    60  	arp.DstProtAddress = data[8+2*arp.HwAddressSize+arp.ProtAddressSize : 8+2*arp.HwAddressSize+2*arp.ProtAddressSize]
    61  
    62  	arp.Contents = data[:arpLength]
    63  	arp.Payload = data[arpLength:]
    64  	return nil
    65  }
    66  
    67  // SerializeTo writes the serialized form of this layer into the
    68  // SerializationBuffer, implementing gopacket.SerializableLayer.
    69  // See the docs for gopacket.SerializableLayer for more info.
    70  func (arp *ARP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
    71  	size := 8 + len(arp.SourceHwAddress) + len(arp.SourceProtAddress) + len(arp.DstHwAddress) + len(arp.DstProtAddress)
    72  	bytes, err := b.PrependBytes(size)
    73  	if err != nil {
    74  		return err
    75  	}
    76  	if opts.FixLengths {
    77  		if len(arp.SourceHwAddress) != len(arp.DstHwAddress) {
    78  			return errors.New("mismatched hardware address sizes")
    79  		}
    80  		arp.HwAddressSize = uint8(len(arp.SourceHwAddress))
    81  		if len(arp.SourceProtAddress) != len(arp.DstProtAddress) {
    82  			return errors.New("mismatched prot address sizes")
    83  		}
    84  		arp.ProtAddressSize = uint8(len(arp.SourceProtAddress))
    85  	}
    86  	binary.BigEndian.PutUint16(bytes, uint16(arp.AddrType))
    87  	binary.BigEndian.PutUint16(bytes[2:], uint16(arp.Protocol))
    88  	bytes[4] = arp.HwAddressSize
    89  	bytes[5] = arp.ProtAddressSize
    90  	binary.BigEndian.PutUint16(bytes[6:], arp.Operation)
    91  	start := 8
    92  	for _, addr := range [][]byte{
    93  		arp.SourceHwAddress,
    94  		arp.SourceProtAddress,
    95  		arp.DstHwAddress,
    96  		arp.DstProtAddress,
    97  	} {
    98  		copy(bytes[start:], addr)
    99  		start += len(addr)
   100  	}
   101  	return nil
   102  }
   103  
   104  // CanDecode returns the set of layer types that this DecodingLayer can decode.
   105  func (arp *ARP) CanDecode() gopacket.LayerClass {
   106  	return LayerTypeARP
   107  }
   108  
   109  // NextLayerType returns the layer type contained by this DecodingLayer.
   110  func (arp *ARP) NextLayerType() gopacket.LayerType {
   111  	return gopacket.LayerTypePayload
   112  }
   113  
   114  func decodeARP(data []byte, p gopacket.PacketBuilder) error {
   115  
   116  	arp := &ARP{}
   117  	return decodingLayerDecoder(arp, data, p)
   118  }