ipv6_fragment.go raw

   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  	"gvisor.dev/gvisor/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  }
 159