gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/tcpip/header/arp.go (about)

     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  }