summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/header/ipv6_fragment.go
blob: 9d09f32eb1ccd2c7f0fae9d1e74cb163ee3df742 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// 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")
}