blob: 9d09f32eb1ccd2c7f0fae9d1e74cb163ee3df742 [file] [log] [blame]
// 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"
"gvisor.dev/gvisor/pkg/tcpip"
)
const (
nextHdrFrag = 0
fragOff = 2
more = 3
idV6 = 4
)
var _ IPv6SerializableExtHdr = (*IPv6SerializableFragmentExtHdr)(nil)
// IPv6SerializableFragmentExtHdr is used to serialize an IPv6 fragment
// extension header as defined in RFC 8200 section 4.5.
type IPv6SerializableFragmentExtHdr struct {
// FragmentOffset is the "fragment offset" field of an IPv6 fragment.
FragmentOffset uint16
// M is the "more" field of an IPv6 fragment.
M bool
// Identification is the "identification" field of an IPv6 fragment.
Identification uint32
}
// identifier implements IPv6SerializableFragmentExtHdr.
func (h *IPv6SerializableFragmentExtHdr) identifier() IPv6ExtensionHeaderIdentifier {
return IPv6FragmentHeader
}
// length implements IPv6SerializableFragmentExtHdr.
func (h *IPv6SerializableFragmentExtHdr) length() int {
return IPv6FragmentHeaderSize
}
// serializeInto implements IPv6SerializableFragmentExtHdr.
func (h *IPv6SerializableFragmentExtHdr) serializeInto(nextHeader uint8, b []byte) int {
// Prevent too many bounds checks.
_ = b[IPv6FragmentHeaderSize:]
binary.BigEndian.PutUint32(b[idV6:], h.Identification)
binary.BigEndian.PutUint16(b[fragOff:], h.FragmentOffset<<ipv6FragmentExtHdrFragmentOffsetShift)
b[nextHdrFrag] = nextHeader
if h.M {
b[more] |= ipv6FragmentExtHdrMFlagMask
}
return IPv6FragmentHeaderSize
}
// IPv6Fragment represents an ipv6 fragment header stored in a byte array.
// Most of the methods of IPv6Fragment access to the underlying slice without
// checking the boundaries and could panic because of 'index out of range'.
// Always call IsValid() to validate an instance of IPv6Fragment before using other methods.
type IPv6Fragment []byte
const (
// IPv6FragmentHeader header is the number used to specify that the next
// header is a fragment header, per RFC 2460.
IPv6FragmentHeader = 44
// IPv6FragmentHeaderSize is the size of the fragment header.
IPv6FragmentHeaderSize = 8
)
// IsValid performs basic validation on the fragment header.
func (b IPv6Fragment) IsValid() bool {
return len(b) >= IPv6FragmentHeaderSize
}
// NextHeader returns the value of the "next header" field of the ipv6 fragment.
func (b IPv6Fragment) NextHeader() uint8 {
return b[nextHdrFrag]
}
// FragmentOffset returns the "fragment offset" field of the ipv6 fragment.
func (b IPv6Fragment) FragmentOffset() uint16 {
return binary.BigEndian.Uint16(b[fragOff:]) >> 3
}
// More returns the "more" field of the ipv6 fragment.
func (b IPv6Fragment) More() bool {
return b[more]&1 > 0
}
// Payload implements Network.Payload.
func (b IPv6Fragment) Payload() []byte {
return b[IPv6FragmentHeaderSize:]
}
// ID returns the value of the identifier field of the ipv6 fragment.
func (b IPv6Fragment) ID() uint32 {
return binary.BigEndian.Uint32(b[idV6:])
}
// TransportProtocol implements Network.TransportProtocol.
func (b IPv6Fragment) TransportProtocol() tcpip.TransportProtocolNumber {
return tcpip.TransportProtocolNumber(b.NextHeader())
}
// The functions below have been added only to satisfy the Network interface.
// Checksum is not supported by IPv6Fragment.
func (b IPv6Fragment) Checksum() uint16 {
panic("not supported")
}
// SourceAddress is not supported by IPv6Fragment.
func (b IPv6Fragment) SourceAddress() tcpip.Address {
panic("not supported")
}
// DestinationAddress is not supported by IPv6Fragment.
func (b IPv6Fragment) DestinationAddress() tcpip.Address {
panic("not supported")
}
// SetSourceAddress is not supported by IPv6Fragment.
func (b IPv6Fragment) SetSourceAddress(tcpip.Address) {
panic("not supported")
}
// SetDestinationAddress is not supported by IPv6Fragment.
func (b IPv6Fragment) SetDestinationAddress(tcpip.Address) {
panic("not supported")
}
// SetChecksum is not supported by IPv6Fragment.
func (b IPv6Fragment) SetChecksum(uint16) {
panic("not supported")
}
// TOS is not supported by IPv6Fragment.
func (b IPv6Fragment) TOS() (uint8, uint32) {
panic("not supported")
}
// SetTOS is not supported by IPv6Fragment.
func (b IPv6Fragment) SetTOS(t uint8, l uint32) {
panic("not supported")
}