github.com/FlowerWrong/netstack@v0.0.0-20191009141956-e5848263af28/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 "github.com/FlowerWrong/netstack/tcpip"
    18  
    19  const (
    20  	// ARPProtocolNumber is the ARP network protocol number.
    21  	ARPProtocolNumber tcpip.NetworkProtocolNumber = 0x0806
    22  
    23  	// ARPSize is the size of an IPv4-over-Ethernet ARP packet.
    24  	ARPSize = 2 + 2 + 1 + 1 + 2 + 2*6 + 2*4
    25  )
    26  
    27  // ARPOp is an ARP opcode.
    28  type ARPOp uint16
    29  
    30  // Typical ARP opcodes defined in RFC 826.
    31  const (
    32  	ARPRequest ARPOp = 1
    33  	ARPReply   ARPOp = 2
    34  )
    35  
    36  // ARP is an ARP packet stored in a byte array as described in RFC 826.
    37  type ARP []byte
    38  
    39  func (a ARP) hardwareAddressSpace() uint16 { return uint16(a[0])<<8 | uint16(a[1]) }
    40  func (a ARP) protocolAddressSpace() uint16 { return uint16(a[2])<<8 | uint16(a[3]) }
    41  func (a ARP) hardwareAddressSize() int     { return int(a[4]) }
    42  func (a ARP) protocolAddressSize() int     { return int(a[5]) }
    43  
    44  // Op is the ARP opcode.
    45  func (a ARP) Op() ARPOp { return ARPOp(a[6])<<8 | ARPOp(a[7]) }
    46  
    47  // SetOp sets the ARP opcode.
    48  func (a ARP) SetOp(op ARPOp) {
    49  	a[6] = uint8(op >> 8)
    50  	a[7] = uint8(op)
    51  }
    52  
    53  // SetIPv4OverEthernet configures the ARP packet for IPv4-over-Ethernet.
    54  func (a ARP) SetIPv4OverEthernet() {
    55  	a[0], a[1] = 0, 1       // htypeEthernet
    56  	a[2], a[3] = 0x08, 0x00 // IPv4ProtocolNumber
    57  	a[4] = 6                // macSize
    58  	a[5] = uint8(IPv4AddressSize)
    59  }
    60  
    61  // HardwareAddressSender is the link address of the sender.
    62  // It is a view on to the ARP packet so it can be used to set the value.
    63  func (a ARP) HardwareAddressSender() []byte {
    64  	const s = 8
    65  	return a[s : s+6]
    66  }
    67  
    68  // ProtocolAddressSender is the protocol address of the sender.
    69  // It is a view on to the ARP packet so it can be used to set the value.
    70  func (a ARP) ProtocolAddressSender() []byte {
    71  	const s = 8 + 6
    72  	return a[s : s+4]
    73  }
    74  
    75  // HardwareAddressTarget is the link address of the target.
    76  // It is a view on to the ARP packet so it can be used to set the value.
    77  func (a ARP) HardwareAddressTarget() []byte {
    78  	const s = 8 + 6 + 4
    79  	return a[s : s+6]
    80  }
    81  
    82  // ProtocolAddressTarget is the protocol address of the target.
    83  // It is a view on to the ARP packet so it can be used to set the value.
    84  func (a ARP) ProtocolAddressTarget() []byte {
    85  	const s = 8 + 6 + 4 + 6
    86  	return a[s : s+4]
    87  }
    88  
    89  // IsValid reports whether this is an ARP packet for IPv4 over Ethernet.
    90  func (a ARP) IsValid() bool {
    91  	if len(a) < ARPSize {
    92  		return false
    93  	}
    94  	const htypeEthernet = 1
    95  	const macSize = 6
    96  	return a.hardwareAddressSpace() == htypeEthernet &&
    97  		a.protocolAddressSpace() == uint16(IPv4ProtocolNumber) &&
    98  		a.hardwareAddressSize() == macSize &&
    99  		a.protocolAddressSize() == IPv4AddressSize
   100  }