arp.go raw

   1  // Copyright 2018 The gVisor Authors.
   2  //
   3  // Licensed under the Apache License, Version 2.0 (the "License");
   4  // you may not use this file except in compliance with the License.
   5  // You may obtain a copy of the License at
   6  //
   7  //     http://www.apache.org/licenses/LICENSE-2.0
   8  //
   9  // Unless required by applicable law or agreed to in writing, software
  10  // distributed under the License is distributed on an "AS IS" BASIS,
  11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12  // See the License for the specific language governing permissions and
  13  // limitations under the License.
  14  
  15  package header
  16  
  17  import (
  18  	"encoding/binary"
  19  
  20  	"gvisor.dev/gvisor/pkg/tcpip"
  21  )
  22  
  23  const (
  24  	// ARPProtocolNumber is the ARP network protocol number.
  25  	ARPProtocolNumber tcpip.NetworkProtocolNumber = 0x0806
  26  
  27  	// ARPSize is the size of an IPv4-over-Ethernet ARP packet.
  28  	ARPSize = 28
  29  )
  30  
  31  // ARPHardwareType is the hardware type for LinkEndpoint in an ARP header.
  32  type ARPHardwareType uint16
  33  
  34  // Typical ARP HardwareType values. Some of the constants have to be specific
  35  // values as they are egressed on the wire in the HTYPE field of an ARP header.
  36  const (
  37  	ARPHardwareNone ARPHardwareType = 0
  38  	// ARPHardwareEther specifically is the HTYPE for Ethernet as specified
  39  	// in the IANA list here:
  40  	//
  41  	// https://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml#arp-parameters-2
  42  	ARPHardwareEther    ARPHardwareType = 1
  43  	ARPHardwareLoopback ARPHardwareType = 2
  44  )
  45  
  46  // ARPOp is an ARP opcode.
  47  type ARPOp uint16
  48  
  49  // Typical ARP opcodes defined in RFC 826.
  50  const (
  51  	ARPRequest ARPOp = 1
  52  	ARPReply   ARPOp = 2
  53  )
  54  
  55  // ARP is an ARP packet stored in a byte array as described in RFC 826.
  56  type ARP []byte
  57  
  58  const (
  59  	hTypeOffset                 = 0
  60  	protocolOffset              = 2
  61  	haAddressSizeOffset         = 4
  62  	protoAddressSizeOffset      = 5
  63  	opCodeOffset                = 6
  64  	senderHAAddressOffset       = 8
  65  	senderProtocolAddressOffset = senderHAAddressOffset + EthernetAddressSize
  66  	targetHAAddressOffset       = senderProtocolAddressOffset + IPv4AddressSize
  67  	targetProtocolAddressOffset = targetHAAddressOffset + EthernetAddressSize
  68  )
  69  
  70  func (a ARP) hardwareAddressType() ARPHardwareType {
  71  	return ARPHardwareType(binary.BigEndian.Uint16(a[hTypeOffset:]))
  72  }
  73  
  74  func (a ARP) protocolAddressSpace() uint16 { return binary.BigEndian.Uint16(a[protocolOffset:]) }
  75  func (a ARP) hardwareAddressSize() int     { return int(a[haAddressSizeOffset]) }
  76  func (a ARP) protocolAddressSize() int     { return int(a[protoAddressSizeOffset]) }
  77  
  78  // Op is the ARP opcode.
  79  func (a ARP) Op() ARPOp { return ARPOp(binary.BigEndian.Uint16(a[opCodeOffset:])) }
  80  
  81  // SetOp sets the ARP opcode.
  82  func (a ARP) SetOp(op ARPOp) {
  83  	binary.BigEndian.PutUint16(a[opCodeOffset:], uint16(op))
  84  }
  85  
  86  // SetIPv4OverEthernet configures the ARP packet for IPv4-over-Ethernet.
  87  func (a ARP) SetIPv4OverEthernet() {
  88  	binary.BigEndian.PutUint16(a[hTypeOffset:], uint16(ARPHardwareEther))
  89  	binary.BigEndian.PutUint16(a[protocolOffset:], uint16(IPv4ProtocolNumber))
  90  	a[haAddressSizeOffset] = EthernetAddressSize
  91  	a[protoAddressSizeOffset] = uint8(IPv4AddressSize)
  92  }
  93  
  94  // HardwareAddressSender is the link address of the sender.
  95  // It is a view on to the ARP packet so it can be used to set the value.
  96  func (a ARP) HardwareAddressSender() []byte {
  97  	return a[senderHAAddressOffset : senderHAAddressOffset+EthernetAddressSize]
  98  }
  99  
 100  // ProtocolAddressSender is the protocol address of the sender.
 101  // It is a view on to the ARP packet so it can be used to set the value.
 102  func (a ARP) ProtocolAddressSender() []byte {
 103  	return a[senderProtocolAddressOffset : senderProtocolAddressOffset+IPv4AddressSize]
 104  }
 105  
 106  // HardwareAddressTarget is the link address of the target.
 107  // It is a view on to the ARP packet so it can be used to set the value.
 108  func (a ARP) HardwareAddressTarget() []byte {
 109  	return a[targetHAAddressOffset : targetHAAddressOffset+EthernetAddressSize]
 110  }
 111  
 112  // ProtocolAddressTarget is the protocol address of the target.
 113  // It is a view on to the ARP packet so it can be used to set the value.
 114  func (a ARP) ProtocolAddressTarget() []byte {
 115  	return a[targetProtocolAddressOffset : targetProtocolAddressOffset+IPv4AddressSize]
 116  }
 117  
 118  // IsValid reports whether this is an ARP packet for IPv4 over Ethernet.
 119  func (a ARP) IsValid() bool {
 120  	if len(a) < ARPSize {
 121  		return false
 122  	}
 123  	return a.hardwareAddressType() == ARPHardwareEther &&
 124  		a.protocolAddressSpace() == uint16(IPv4ProtocolNumber) &&
 125  		a.hardwareAddressSize() == EthernetAddressSize &&
 126  		a.protocolAddressSize() == IPv4AddressSize
 127  }
 128