mirror of
https://github.com/SagerNet/sing-tun.git
synced 2025-04-02 19:37:40 +03:00
158 lines
4.7 KiB
Go
158 lines
4.7 KiB
Go
// 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/sagernet/sing-tun/internal/gtcpip"
|
|
)
|
|
|
|
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")
|
|
}
|