github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/tcpip/header/ipv6_fragment.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/nicocha30/gvisor-ligolo/pkg/tcpip"
    21  )
    22  
    23  const (
    24  	nextHdrFrag = 0
    25  	fragOff     = 2
    26  	more        = 3
    27  	idV6        = 4
    28  )
    29  
    30  var _ IPv6SerializableExtHdr = (*IPv6SerializableFragmentExtHdr)(nil)
    31  
    32  // IPv6SerializableFragmentExtHdr is used to serialize an IPv6 fragment
    33  // extension header as defined in RFC 8200 section 4.5.
    34  type IPv6SerializableFragmentExtHdr struct {
    35  	// FragmentOffset is the "fragment offset" field of an IPv6 fragment.
    36  	FragmentOffset uint16
    37  
    38  	// M is the "more" field of an IPv6 fragment.
    39  	M bool
    40  
    41  	// Identification is the "identification" field of an IPv6 fragment.
    42  	Identification uint32
    43  }
    44  
    45  // identifier implements IPv6SerializableFragmentExtHdr.
    46  func (h *IPv6SerializableFragmentExtHdr) identifier() IPv6ExtensionHeaderIdentifier {
    47  	return IPv6FragmentHeader
    48  }
    49  
    50  // length implements IPv6SerializableFragmentExtHdr.
    51  func (h *IPv6SerializableFragmentExtHdr) length() int {
    52  	return IPv6FragmentHeaderSize
    53  }
    54  
    55  // serializeInto implements IPv6SerializableFragmentExtHdr.
    56  func (h *IPv6SerializableFragmentExtHdr) serializeInto(nextHeader uint8, b []byte) int {
    57  	// Prevent too many bounds checks.
    58  	_ = b[IPv6FragmentHeaderSize:]
    59  	binary.BigEndian.PutUint32(b[idV6:], h.Identification)
    60  	binary.BigEndian.PutUint16(b[fragOff:], h.FragmentOffset<<ipv6FragmentExtHdrFragmentOffsetShift)
    61  	b[nextHdrFrag] = nextHeader
    62  	if h.M {
    63  		b[more] |= ipv6FragmentExtHdrMFlagMask
    64  	}
    65  	return IPv6FragmentHeaderSize
    66  }
    67  
    68  // IPv6Fragment represents an ipv6 fragment header stored in a byte array.
    69  // Most of the methods of IPv6Fragment access to the underlying slice without
    70  // checking the boundaries and could panic because of 'index out of range'.
    71  // Always call IsValid() to validate an instance of IPv6Fragment before using other methods.
    72  type IPv6Fragment []byte
    73  
    74  const (
    75  	// IPv6FragmentHeader header is the number used to specify that the next
    76  	// header is a fragment header, per RFC 2460.
    77  	IPv6FragmentHeader = 44
    78  
    79  	// IPv6FragmentHeaderSize is the size of the fragment header.
    80  	IPv6FragmentHeaderSize = 8
    81  )
    82  
    83  // IsValid performs basic validation on the fragment header.
    84  func (b IPv6Fragment) IsValid() bool {
    85  	return len(b) >= IPv6FragmentHeaderSize
    86  }
    87  
    88  // NextHeader returns the value of the "next header" field of the ipv6 fragment.
    89  func (b IPv6Fragment) NextHeader() uint8 {
    90  	return b[nextHdrFrag]
    91  }
    92  
    93  // FragmentOffset returns the "fragment offset" field of the ipv6 fragment.
    94  func (b IPv6Fragment) FragmentOffset() uint16 {
    95  	return binary.BigEndian.Uint16(b[fragOff:]) >> 3
    96  }
    97  
    98  // More returns the "more" field of the ipv6 fragment.
    99  func (b IPv6Fragment) More() bool {
   100  	return b[more]&1 > 0
   101  }
   102  
   103  // Payload implements Network.Payload.
   104  func (b IPv6Fragment) Payload() []byte {
   105  	return b[IPv6FragmentHeaderSize:]
   106  }
   107  
   108  // ID returns the value of the identifier field of the ipv6 fragment.
   109  func (b IPv6Fragment) ID() uint32 {
   110  	return binary.BigEndian.Uint32(b[idV6:])
   111  }
   112  
   113  // TransportProtocol implements Network.TransportProtocol.
   114  func (b IPv6Fragment) TransportProtocol() tcpip.TransportProtocolNumber {
   115  	return tcpip.TransportProtocolNumber(b.NextHeader())
   116  }
   117  
   118  // The functions below have been added only to satisfy the Network interface.
   119  
   120  // Checksum is not supported by IPv6Fragment.
   121  func (b IPv6Fragment) Checksum() uint16 {
   122  	panic("not supported")
   123  }
   124  
   125  // SourceAddress is not supported by IPv6Fragment.
   126  func (b IPv6Fragment) SourceAddress() tcpip.Address {
   127  	panic("not supported")
   128  }
   129  
   130  // DestinationAddress is not supported by IPv6Fragment.
   131  func (b IPv6Fragment) DestinationAddress() tcpip.Address {
   132  	panic("not supported")
   133  }
   134  
   135  // SetSourceAddress is not supported by IPv6Fragment.
   136  func (b IPv6Fragment) SetSourceAddress(tcpip.Address) {
   137  	panic("not supported")
   138  }
   139  
   140  // SetDestinationAddress is not supported by IPv6Fragment.
   141  func (b IPv6Fragment) SetDestinationAddress(tcpip.Address) {
   142  	panic("not supported")
   143  }
   144  
   145  // SetChecksum is not supported by IPv6Fragment.
   146  func (b IPv6Fragment) SetChecksum(uint16) {
   147  	panic("not supported")
   148  }
   149  
   150  // TOS is not supported by IPv6Fragment.
   151  func (b IPv6Fragment) TOS() (uint8, uint32) {
   152  	panic("not supported")
   153  }
   154  
   155  // SetTOS is not supported by IPv6Fragment.
   156  func (b IPv6Fragment) SetTOS(t uint8, l uint32) {
   157  	panic("not supported")
   158  }