github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/tcpip/header/icmpv6.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 "github.com/nicocha30/gvisor-ligolo/pkg/tcpip/checksum" 22 ) 23 24 // ICMPv6 represents an ICMPv6 header stored in a byte array. 25 type ICMPv6 []byte 26 27 const ( 28 // ICMPv6HeaderSize is the size of the ICMPv6 header. That is, the 29 // sum of the size of the ICMPv6 Type, Code and Checksum fields, as 30 // per RFC 4443 section 2.1. After the ICMPv6 header, the ICMPv6 31 // message body begins. 32 ICMPv6HeaderSize = 4 33 34 // ICMPv6MinimumSize is the minimum size of a valid ICMP packet. 35 ICMPv6MinimumSize = 8 36 37 // ICMPv6PayloadOffset is the offset of the payload in an 38 // ICMP packet. 39 ICMPv6PayloadOffset = 8 40 41 // ICMPv6ProtocolNumber is the ICMP transport protocol number. 42 ICMPv6ProtocolNumber tcpip.TransportProtocolNumber = 58 43 44 // ICMPv6NeighborSolicitMinimumSize is the minimum size of a 45 // neighbor solicitation packet. 46 ICMPv6NeighborSolicitMinimumSize = ICMPv6HeaderSize + NDPNSMinimumSize 47 48 // ICMPv6NeighborAdvertMinimumSize is the minimum size of a 49 // neighbor advertisement packet. 50 ICMPv6NeighborAdvertMinimumSize = ICMPv6HeaderSize + NDPNAMinimumSize 51 52 // ICMPv6EchoMinimumSize is the minimum size of a valid echo packet. 53 ICMPv6EchoMinimumSize = 8 54 55 // ICMPv6ErrorHeaderSize is the size of an ICMP error packet header, 56 // as per RFC 4443, Apendix A, item 4 and the errata. 57 // ... all ICMP error messages shall have exactly 58 // 32 bits of type-specific data, so that receivers can reliably find 59 // the embedded invoking packet even when they don't recognize the 60 // ICMP message Type. 61 ICMPv6ErrorHeaderSize = 8 62 63 // ICMPv6DstUnreachableMinimumSize is the minimum size of a valid ICMP 64 // destination unreachable packet. 65 ICMPv6DstUnreachableMinimumSize = ICMPv6MinimumSize 66 67 // ICMPv6PacketTooBigMinimumSize is the minimum size of a valid ICMP 68 // packet-too-big packet. 69 ICMPv6PacketTooBigMinimumSize = ICMPv6MinimumSize 70 71 // ICMPv6ChecksumOffset is the offset of the checksum field 72 // in an ICMPv6 message. 73 ICMPv6ChecksumOffset = 2 74 75 // icmpv6PointerOffset is the offset of the pointer 76 // in an ICMPv6 Parameter problem message. 77 icmpv6PointerOffset = 4 78 79 // icmpv6MTUOffset is the offset of the MTU field in an ICMPv6 80 // PacketTooBig message. 81 icmpv6MTUOffset = 4 82 83 // icmpv6IdentOffset is the offset of the ident field 84 // in a ICMPv6 Echo Request/Reply message. 85 icmpv6IdentOffset = 4 86 87 // icmpv6SequenceOffset is the offset of the sequence field 88 // in a ICMPv6 Echo Request/Reply message. 89 icmpv6SequenceOffset = 6 90 91 // NDPHopLimit is the expected IP hop limit value of 255 for received 92 // NDP packets, as per RFC 4861 sections 4.1 - 4.5, 6.1.1, 6.1.2, 7.1.1, 93 // 7.1.2 and 8.1. If the hop limit value is not 255, nodes MUST silently 94 // drop the NDP packet. All outgoing NDP packets must use this value for 95 // its IP hop limit field. 96 NDPHopLimit = 255 97 ) 98 99 // ICMPv6Type is the ICMP type field described in RFC 4443. 100 type ICMPv6Type byte 101 102 // Values for use in the Type field of ICMPv6 packet from RFC 4433. 103 const ( 104 ICMPv6DstUnreachable ICMPv6Type = 1 105 ICMPv6PacketTooBig ICMPv6Type = 2 106 ICMPv6TimeExceeded ICMPv6Type = 3 107 ICMPv6ParamProblem ICMPv6Type = 4 108 ICMPv6EchoRequest ICMPv6Type = 128 109 ICMPv6EchoReply ICMPv6Type = 129 110 111 // Neighbor Discovery Protocol (NDP) messages, see RFC 4861. 112 113 ICMPv6RouterSolicit ICMPv6Type = 133 114 ICMPv6RouterAdvert ICMPv6Type = 134 115 ICMPv6NeighborSolicit ICMPv6Type = 135 116 ICMPv6NeighborAdvert ICMPv6Type = 136 117 ICMPv6RedirectMsg ICMPv6Type = 137 118 119 // Multicast Listener Discovery (MLD) messages, see RFC 2710. 120 121 ICMPv6MulticastListenerQuery ICMPv6Type = 130 122 ICMPv6MulticastListenerReport ICMPv6Type = 131 123 ICMPv6MulticastListenerDone ICMPv6Type = 132 124 125 // Multicast Listener Discovert Version 2 (MLDv2) messages, see RFC 3810. 126 127 ICMPv6MulticastListenerV2Report ICMPv6Type = 143 128 ) 129 130 // IsErrorType returns true if the receiver is an ICMP error type. 131 func (typ ICMPv6Type) IsErrorType() bool { 132 // Per RFC 4443 section 2.1: 133 // ICMPv6 messages are grouped into two classes: error messages and 134 // informational messages. Error messages are identified as such by a 135 // zero in the high-order bit of their message Type field values. Thus, 136 // error messages have message types from 0 to 127; informational 137 // messages have message types from 128 to 255. 138 return typ&0x80 == 0 139 } 140 141 // ICMPv6Code is the ICMP Code field described in RFC 4443. 142 type ICMPv6Code byte 143 144 // ICMP codes used with Destination Unreachable (Type 1). As per RFC 4443 145 // section 3.1. 146 const ( 147 ICMPv6NetworkUnreachable ICMPv6Code = 0 148 ICMPv6Prohibited ICMPv6Code = 1 149 ICMPv6BeyondScope ICMPv6Code = 2 150 ICMPv6AddressUnreachable ICMPv6Code = 3 151 ICMPv6PortUnreachable ICMPv6Code = 4 152 ICMPv6Policy ICMPv6Code = 5 153 ICMPv6RejectRoute ICMPv6Code = 6 154 ) 155 156 // ICMP codes used with Time Exceeded (Type 3). As per RFC 4443 section 3.3. 157 const ( 158 ICMPv6HopLimitExceeded ICMPv6Code = 0 159 ICMPv6ReassemblyTimeout ICMPv6Code = 1 160 ) 161 162 // ICMP codes used with Parameter Problem (Type 4). As per RFC 4443 section 3.4. 163 const ( 164 // ICMPv6ErroneousHeader indicates an erroneous header field was encountered. 165 ICMPv6ErroneousHeader ICMPv6Code = 0 166 167 // ICMPv6UnknownHeader indicates an unrecognized Next Header type encountered. 168 ICMPv6UnknownHeader ICMPv6Code = 1 169 170 // ICMPv6UnknownOption indicates an unrecognized IPv6 option was encountered. 171 ICMPv6UnknownOption ICMPv6Code = 2 172 ) 173 174 // ICMPv6UnusedCode is the code value used with ICMPv6 messages which don't use 175 // the code field. (Types not mentioned above.) 176 const ICMPv6UnusedCode ICMPv6Code = 0 177 178 // Type is the ICMP type field. 179 func (b ICMPv6) Type() ICMPv6Type { return ICMPv6Type(b[0]) } 180 181 // SetType sets the ICMP type field. 182 func (b ICMPv6) SetType(t ICMPv6Type) { b[0] = byte(t) } 183 184 // Code is the ICMP code field. Its meaning depends on the value of Type. 185 func (b ICMPv6) Code() ICMPv6Code { return ICMPv6Code(b[1]) } 186 187 // SetCode sets the ICMP code field. 188 func (b ICMPv6) SetCode(c ICMPv6Code) { b[1] = byte(c) } 189 190 // TypeSpecific returns the type specific data field. 191 func (b ICMPv6) TypeSpecific() uint32 { 192 return binary.BigEndian.Uint32(b[icmpv6PointerOffset:]) 193 } 194 195 // SetTypeSpecific sets the type specific data field. 196 func (b ICMPv6) SetTypeSpecific(val uint32) { 197 binary.BigEndian.PutUint32(b[icmpv6PointerOffset:], val) 198 } 199 200 // Checksum is the ICMP checksum field. 201 func (b ICMPv6) Checksum() uint16 { 202 return binary.BigEndian.Uint16(b[ICMPv6ChecksumOffset:]) 203 } 204 205 // SetChecksum sets the ICMP checksum field. 206 func (b ICMPv6) SetChecksum(cs uint16) { 207 checksum.Put(b[ICMPv6ChecksumOffset:], cs) 208 } 209 210 // SourcePort implements Transport.SourcePort. 211 func (ICMPv6) SourcePort() uint16 { 212 return 0 213 } 214 215 // DestinationPort implements Transport.DestinationPort. 216 func (ICMPv6) DestinationPort() uint16 { 217 return 0 218 } 219 220 // SetSourcePort implements Transport.SetSourcePort. 221 func (ICMPv6) SetSourcePort(uint16) { 222 } 223 224 // SetDestinationPort implements Transport.SetDestinationPort. 225 func (ICMPv6) SetDestinationPort(uint16) { 226 } 227 228 // MTU retrieves the MTU field from an ICMPv6 message. 229 func (b ICMPv6) MTU() uint32 { 230 return binary.BigEndian.Uint32(b[icmpv6MTUOffset:]) 231 } 232 233 // SetMTU sets the MTU field from an ICMPv6 message. 234 func (b ICMPv6) SetMTU(mtu uint32) { 235 binary.BigEndian.PutUint32(b[icmpv6MTUOffset:], mtu) 236 } 237 238 // Ident retrieves the Ident field from an ICMPv6 message. 239 func (b ICMPv6) Ident() uint16 { 240 return binary.BigEndian.Uint16(b[icmpv6IdentOffset:]) 241 } 242 243 // SetIdent sets the Ident field from an ICMPv6 message. 244 func (b ICMPv6) SetIdent(ident uint16) { 245 binary.BigEndian.PutUint16(b[icmpv6IdentOffset:], ident) 246 } 247 248 // SetIdentWithChecksumUpdate sets the Ident field and updates the checksum. 249 func (b ICMPv6) SetIdentWithChecksumUpdate(new uint16) { 250 old := b.Ident() 251 b.SetIdent(new) 252 b.SetChecksum(^checksumUpdate2ByteAlignedUint16(^b.Checksum(), old, new)) 253 } 254 255 // Sequence retrieves the Sequence field from an ICMPv6 message. 256 func (b ICMPv6) Sequence() uint16 { 257 return binary.BigEndian.Uint16(b[icmpv6SequenceOffset:]) 258 } 259 260 // SetSequence sets the Sequence field from an ICMPv6 message. 261 func (b ICMPv6) SetSequence(sequence uint16) { 262 binary.BigEndian.PutUint16(b[icmpv6SequenceOffset:], sequence) 263 } 264 265 // MessageBody returns the message body as defined by RFC 4443 section 2.1; the 266 // portion of the ICMPv6 buffer after the first ICMPv6HeaderSize bytes. 267 func (b ICMPv6) MessageBody() []byte { 268 return b[ICMPv6HeaderSize:] 269 } 270 271 // Payload implements Transport.Payload. 272 func (b ICMPv6) Payload() []byte { 273 return b[ICMPv6PayloadOffset:] 274 } 275 276 // ICMPv6ChecksumParams contains parameters to calculate ICMPv6 checksum. 277 type ICMPv6ChecksumParams struct { 278 Header ICMPv6 279 Src tcpip.Address 280 Dst tcpip.Address 281 PayloadCsum uint16 282 PayloadLen int 283 } 284 285 // ICMPv6Checksum calculates the ICMP checksum over the provided ICMPv6 header, 286 // IPv6 src/dst addresses and the payload. 287 func ICMPv6Checksum(params ICMPv6ChecksumParams) uint16 { 288 h := params.Header 289 290 xsum := PseudoHeaderChecksum(ICMPv6ProtocolNumber, params.Src, params.Dst, uint16(len(h)+params.PayloadLen)) 291 xsum = checksum.Combine(xsum, params.PayloadCsum) 292 293 // h[2:4] is the checksum itself, skip it to avoid checksumming the checksum. 294 xsum = checksum.Checksum(h[:2], xsum) 295 xsum = checksum.Checksum(h[4:], xsum) 296 297 return ^xsum 298 } 299 300 // UpdateChecksumPseudoHeaderAddress updates the checksum to reflect an 301 // updated address in the pseudo header. 302 func (b ICMPv6) UpdateChecksumPseudoHeaderAddress(old, new tcpip.Address) { 303 b.SetChecksum(^checksumUpdate2ByteAlignedAddress(^b.Checksum(), old, new)) 304 }