| // Copyright 2018 The gVisor Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package header |
| |
| import ( |
| "encoding/binary" |
| |
| "github.com/google/netstack/tcpip" |
| ) |
| |
| const ( |
| dstMAC = 0 |
| srcMAC = 6 |
| ethType = 12 |
| ) |
| |
| // EthernetFields contains the fields of an ethernet frame header. It is used to |
| // describe the fields of a frame that needs to be encoded. |
| type EthernetFields struct { |
| // SrcAddr is the "MAC source" field of an ethernet frame header. |
| SrcAddr tcpip.LinkAddress |
| |
| // DstAddr is the "MAC destination" field of an ethernet frame header. |
| DstAddr tcpip.LinkAddress |
| |
| // Type is the "ethertype" field of an ethernet frame header. |
| Type tcpip.NetworkProtocolNumber |
| } |
| |
| // Ethernet represents an ethernet frame header stored in a byte array. |
| type Ethernet []byte |
| |
| const ( |
| // EthernetMinimumSize is the minimum size of a valid ethernet frame. |
| EthernetMinimumSize = 14 |
| |
| // EthernetAddressSize is the size, in bytes, of an ethernet address. |
| EthernetAddressSize = 6 |
| |
| // unspecifiedEthernetAddress is the unspecified ethernet address |
| // (all bits set to 0). |
| unspecifiedEthernetAddress = tcpip.LinkAddress("\x00\x00\x00\x00\x00\x00") |
| |
| // unicastMulticastFlagMask is the mask of the least significant bit in |
| // the first octet (in network byte order) of an ethernet address that |
| // determines whether the ethernet address is a unicast or multicast. If |
| // the masked bit is a 1, then the address is a multicast, unicast |
| // otherwise. |
| // |
| // See the IEEE Std 802-2001 document for more details. Specifically, |
| // section 9.2.1 of http://ieee802.org/secmail/pdfocSP2xXA6d.pdf: |
| // "A 48-bit universal address consists of two parts. The first 24 bits |
| // correspond to the OUI as assigned by the IEEE, expect that the |
| // assignee may set the LSB of the first octet to 1 for group addresses |
| // or set it to 0 for individual addresses." |
| unicastMulticastFlagMask = 1 |
| |
| // unicastMulticastFlagByteIdx is the byte that holds the |
| // unicast/multicast flag. See unicastMulticastFlagMask. |
| unicastMulticastFlagByteIdx = 0 |
| ) |
| |
| const ( |
| // EthernetProtocolAll is a catch-all for all protocols carried inside |
| // an ethernet frame. It is mainly used to create packet sockets that |
| // capture all traffic. |
| EthernetProtocolAll tcpip.NetworkProtocolNumber = 0x0003 |
| |
| // EthernetProtocolPUP is the PARC Universial Packet protocol ethertype. |
| EthernetProtocolPUP tcpip.NetworkProtocolNumber = 0x0200 |
| ) |
| |
| // Ethertypes holds the protocol numbers describing the payload of an ethernet |
| // frame. These types aren't necessarily supported by netstack, but can be used |
| // to catch all traffic of a type via packet endpoints. |
| var Ethertypes = []tcpip.NetworkProtocolNumber{ |
| EthernetProtocolAll, |
| EthernetProtocolPUP, |
| } |
| |
| // SourceAddress returns the "MAC source" field of the ethernet frame header. |
| func (b Ethernet) SourceAddress() tcpip.LinkAddress { |
| return tcpip.LinkAddress(b[srcMAC:][:EthernetAddressSize]) |
| } |
| |
| // DestinationAddress returns the "MAC destination" field of the ethernet frame |
| // header. |
| func (b Ethernet) DestinationAddress() tcpip.LinkAddress { |
| return tcpip.LinkAddress(b[dstMAC:][:EthernetAddressSize]) |
| } |
| |
| // Type returns the "ethertype" field of the ethernet frame header. |
| func (b Ethernet) Type() tcpip.NetworkProtocolNumber { |
| return tcpip.NetworkProtocolNumber(binary.BigEndian.Uint16(b[ethType:])) |
| } |
| |
| // Encode encodes all the fields of the ethernet frame header. |
| func (b Ethernet) Encode(e *EthernetFields) { |
| binary.BigEndian.PutUint16(b[ethType:], uint16(e.Type)) |
| copy(b[srcMAC:][:EthernetAddressSize], e.SrcAddr) |
| copy(b[dstMAC:][:EthernetAddressSize], e.DstAddr) |
| } |
| |
| // IsValidUnicastEthernetAddress returns true if addr is a valid unicast |
| // ethernet address. |
| func IsValidUnicastEthernetAddress(addr tcpip.LinkAddress) bool { |
| // Must be of the right length. |
| if len(addr) != EthernetAddressSize { |
| return false |
| } |
| |
| // Must not be unspecified. |
| if addr == unspecifiedEthernetAddress { |
| return false |
| } |
| |
| // Must not be a multicast. |
| if addr[unicastMulticastFlagByteIdx]&unicastMulticastFlagMask != 0 { |
| return false |
| } |
| |
| // addr is a valid unicast ethernet address. |
| return true |
| } |