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 }