github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/tcpip/header/eth.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 "github.com/MerlinKodo/gvisor/pkg/tcpip" 21 ) 22 23 const ( 24 dstMAC = 0 25 srcMAC = 6 26 ethType = 12 27 ) 28 29 // EthernetFields contains the fields of an ethernet frame header. It is used to 30 // describe the fields of a frame that needs to be encoded. 31 type EthernetFields struct { 32 // SrcAddr is the "MAC source" field of an ethernet frame header. 33 SrcAddr tcpip.LinkAddress 34 35 // DstAddr is the "MAC destination" field of an ethernet frame header. 36 DstAddr tcpip.LinkAddress 37 38 // Type is the "ethertype" field of an ethernet frame header. 39 Type tcpip.NetworkProtocolNumber 40 } 41 42 // Ethernet represents an ethernet frame header stored in a byte array. 43 type Ethernet []byte 44 45 const ( 46 // EthernetMinimumSize is the minimum size of a valid ethernet frame. 47 EthernetMinimumSize = 14 48 49 // EthernetAddressSize is the size, in bytes, of an ethernet address. 50 EthernetAddressSize = 6 51 52 // UnspecifiedEthernetAddress is the unspecified ethernet address 53 // (all bits set to 0). 54 UnspecifiedEthernetAddress = tcpip.LinkAddress("\x00\x00\x00\x00\x00\x00") 55 56 // EthernetBroadcastAddress is an ethernet address that addresses every node 57 // on a local link. 58 EthernetBroadcastAddress = tcpip.LinkAddress("\xff\xff\xff\xff\xff\xff") 59 60 // unicastMulticastFlagMask is the mask of the least significant bit in 61 // the first octet (in network byte order) of an ethernet address that 62 // determines whether the ethernet address is a unicast or multicast. If 63 // the masked bit is a 1, then the address is a multicast, unicast 64 // otherwise. 65 // 66 // See the IEEE Std 802-2001 document for more details. Specifically, 67 // section 9.2.1 of http://ieee802.org/secmail/pdfocSP2xXA6d.pdf: 68 // "A 48-bit universal address consists of two parts. The first 24 bits 69 // correspond to the OUI as assigned by the IEEE, expect that the 70 // assignee may set the LSB of the first octet to 1 for group addresses 71 // or set it to 0 for individual addresses." 72 unicastMulticastFlagMask = 1 73 74 // unicastMulticastFlagByteIdx is the byte that holds the 75 // unicast/multicast flag. See unicastMulticastFlagMask. 76 unicastMulticastFlagByteIdx = 0 77 ) 78 79 const ( 80 // EthernetProtocolAll is a catch-all for all protocols carried inside 81 // an ethernet frame. It is mainly used to create packet sockets that 82 // capture all traffic. 83 EthernetProtocolAll tcpip.NetworkProtocolNumber = 0x0003 84 85 // EthernetProtocolPUP is the PARC Universial Packet protocol ethertype. 86 EthernetProtocolPUP tcpip.NetworkProtocolNumber = 0x0200 87 ) 88 89 // Ethertypes holds the protocol numbers describing the payload of an ethernet 90 // frame. These types aren't necessarily supported by netstack, but can be used 91 // to catch all traffic of a type via packet endpoints. 92 var Ethertypes = []tcpip.NetworkProtocolNumber{ 93 EthernetProtocolAll, 94 EthernetProtocolPUP, 95 } 96 97 // SourceAddress returns the "MAC source" field of the ethernet frame header. 98 func (b Ethernet) SourceAddress() tcpip.LinkAddress { 99 return tcpip.LinkAddress(b[srcMAC:][:EthernetAddressSize]) 100 } 101 102 // DestinationAddress returns the "MAC destination" field of the ethernet frame 103 // header. 104 func (b Ethernet) DestinationAddress() tcpip.LinkAddress { 105 return tcpip.LinkAddress(b[dstMAC:][:EthernetAddressSize]) 106 } 107 108 // Type returns the "ethertype" field of the ethernet frame header. 109 func (b Ethernet) Type() tcpip.NetworkProtocolNumber { 110 return tcpip.NetworkProtocolNumber(binary.BigEndian.Uint16(b[ethType:])) 111 } 112 113 // Encode encodes all the fields of the ethernet frame header. 114 func (b Ethernet) Encode(e *EthernetFields) { 115 binary.BigEndian.PutUint16(b[ethType:], uint16(e.Type)) 116 copy(b[srcMAC:][:EthernetAddressSize], e.SrcAddr) 117 copy(b[dstMAC:][:EthernetAddressSize], e.DstAddr) 118 } 119 120 // IsMulticastEthernetAddress returns true if the address is a multicast 121 // ethernet address. 122 func IsMulticastEthernetAddress(addr tcpip.LinkAddress) bool { 123 if len(addr) != EthernetAddressSize { 124 return false 125 } 126 127 return addr[unicastMulticastFlagByteIdx]&unicastMulticastFlagMask != 0 128 } 129 130 // IsValidUnicastEthernetAddress returns true if the address is a unicast 131 // ethernet address. 132 func IsValidUnicastEthernetAddress(addr tcpip.LinkAddress) bool { 133 if len(addr) != EthernetAddressSize { 134 return false 135 } 136 137 if addr == UnspecifiedEthernetAddress { 138 return false 139 } 140 141 if addr[unicastMulticastFlagByteIdx]&unicastMulticastFlagMask != 0 { 142 return false 143 } 144 145 return true 146 } 147 148 // EthernetAddressFromMulticastIPv4Address returns a multicast Ethernet address 149 // for a multicast IPv4 address. 150 // 151 // addr MUST be a multicast IPv4 address. 152 func EthernetAddressFromMulticastIPv4Address(addr tcpip.Address) tcpip.LinkAddress { 153 var linkAddrBytes [EthernetAddressSize]byte 154 // RFC 1112 Host Extensions for IP Multicasting 155 // 156 // 6.4. Extensions to an Ethernet Local Network Module: 157 // 158 // An IP host group address is mapped to an Ethernet multicast 159 // address by placing the low-order 23-bits of the IP address 160 // into the low-order 23 bits of the Ethernet multicast address 161 // 01-00-5E-00-00-00 (hex). 162 addrBytes := addr.As4() 163 linkAddrBytes[0] = 0x1 164 linkAddrBytes[2] = 0x5e 165 linkAddrBytes[3] = addrBytes[1] & 0x7F 166 copy(linkAddrBytes[4:], addrBytes[IPv4AddressSize-2:]) 167 return tcpip.LinkAddress(linkAddrBytes[:]) 168 } 169 170 // EthernetAddressFromMulticastIPv6Address returns a multicast Ethernet address 171 // for a multicast IPv6 address. 172 // 173 // addr MUST be a multicast IPv6 address. 174 func EthernetAddressFromMulticastIPv6Address(addr tcpip.Address) tcpip.LinkAddress { 175 // RFC 2464 Transmission of IPv6 Packets over Ethernet Networks 176 // 177 // 7. Address Mapping -- Multicast 178 // 179 // An IPv6 packet with a multicast destination address DST, 180 // consisting of the sixteen octets DST[1] through DST[16], is 181 // transmitted to the Ethernet multicast address whose first 182 // two octets are the value 3333 hexadecimal and whose last 183 // four octets are the last four octets of DST. 184 addrBytes := addr.As16() 185 linkAddrBytes := []byte(addrBytes[IPv6AddressSize-EthernetAddressSize:]) 186 linkAddrBytes[0] = 0x33 187 linkAddrBytes[1] = 0x33 188 return tcpip.LinkAddress(linkAddrBytes[:]) 189 }