github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/tcpip/header/icmpv4.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 // ICMPv4 represents an ICMPv4 header stored in a byte array. 25 type ICMPv4 []byte 26 27 const ( 28 // ICMPv4PayloadOffset defines the start of ICMP payload. 29 ICMPv4PayloadOffset = 8 30 31 // ICMPv4MinimumSize is the minimum size of a valid ICMP packet. 32 ICMPv4MinimumSize = 8 33 34 // ICMPv4MinimumErrorPayloadSize Is the smallest number of bytes of an 35 // errant packet's transport layer that an ICMP error type packet should 36 // attempt to send as per RFC 792 (see each type) and RFC 1122 37 // section 3.2.2 which states: 38 // Every ICMP error message includes the Internet header and at 39 // least the first 8 data octets of the datagram that triggered 40 // the error; more than 8 octets MAY be sent; this header and data 41 // MUST be unchanged from the received datagram. 42 // 43 // RFC 792 shows: 44 // 0 1 2 3 45 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 46 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 47 // | Type | Code | Checksum | 48 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 49 // | unused | 50 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51 // | Internet Header + 64 bits of Original Data Datagram | 52 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 53 ICMPv4MinimumErrorPayloadSize = 8 54 55 // ICMPv4ProtocolNumber is the ICMP transport protocol number. 56 ICMPv4ProtocolNumber tcpip.TransportProtocolNumber = 1 57 58 // icmpv4ChecksumOffset is the offset of the checksum field 59 // in an ICMPv4 message. 60 icmpv4ChecksumOffset = 2 61 62 // icmpv4MTUOffset is the offset of the MTU field 63 // in an ICMPv4FragmentationNeeded message. 64 icmpv4MTUOffset = 6 65 66 // icmpv4IdentOffset is the offset of the ident field 67 // in an ICMPv4EchoRequest/Reply message. 68 icmpv4IdentOffset = 4 69 70 // icmpv4PointerOffset is the offset of the pointer field 71 // in an ICMPv4ParamProblem message. 72 icmpv4PointerOffset = 4 73 74 // icmpv4SequenceOffset is the offset of the sequence field 75 // in an ICMPv4EchoRequest/Reply message. 76 icmpv4SequenceOffset = 6 77 ) 78 79 // ICMPv4Type is the ICMP type field described in RFC 792. 80 type ICMPv4Type byte 81 82 // ICMPv4Code is the ICMP code field described in RFC 792. 83 type ICMPv4Code byte 84 85 // Typical values of ICMPv4Type defined in RFC 792. 86 const ( 87 ICMPv4EchoReply ICMPv4Type = 0 88 ICMPv4DstUnreachable ICMPv4Type = 3 89 ICMPv4SrcQuench ICMPv4Type = 4 90 ICMPv4Redirect ICMPv4Type = 5 91 ICMPv4Echo ICMPv4Type = 8 92 ICMPv4TimeExceeded ICMPv4Type = 11 93 ICMPv4ParamProblem ICMPv4Type = 12 94 ICMPv4Timestamp ICMPv4Type = 13 95 ICMPv4TimestampReply ICMPv4Type = 14 96 ICMPv4InfoRequest ICMPv4Type = 15 97 ICMPv4InfoReply ICMPv4Type = 16 98 ) 99 100 // ICMP codes for ICMPv4 Time Exceeded messages as defined in RFC 792. 101 const ( 102 ICMPv4TTLExceeded ICMPv4Code = 0 103 ICMPv4ReassemblyTimeout ICMPv4Code = 1 104 ) 105 106 // ICMP codes for ICMPv4 Destination Unreachable messages as defined in RFC 792, 107 // RFC 1122 section 3.2.2.1 and RFC 1812 section 5.2.7.1. 108 const ( 109 ICMPv4NetUnreachable ICMPv4Code = 0 110 ICMPv4HostUnreachable ICMPv4Code = 1 111 ICMPv4ProtoUnreachable ICMPv4Code = 2 112 ICMPv4PortUnreachable ICMPv4Code = 3 113 ICMPv4FragmentationNeeded ICMPv4Code = 4 114 ICMPv4SourceRouteFailed ICMPv4Code = 5 115 ICMPv4DestinationNetworkUnknown ICMPv4Code = 6 116 ICMPv4DestinationHostUnknown ICMPv4Code = 7 117 ICMPv4SourceHostIsolated ICMPv4Code = 8 118 ICMPv4NetProhibited ICMPv4Code = 9 119 ICMPv4HostProhibited ICMPv4Code = 10 120 ICMPv4NetUnreachableForTos ICMPv4Code = 11 121 ICMPv4HostUnreachableForTos ICMPv4Code = 12 122 ICMPv4AdminProhibited ICMPv4Code = 13 123 ICMPv4HostPrecedenceViolation ICMPv4Code = 14 124 ICMPv4PrecedenceCutInEffect ICMPv4Code = 15 125 ) 126 127 // ICMPv4UnusedCode is a code to use in ICMP messages where no code is needed. 128 const ICMPv4UnusedCode ICMPv4Code = 0 129 130 // Type is the ICMP type field. 131 func (b ICMPv4) Type() ICMPv4Type { return ICMPv4Type(b[0]) } 132 133 // SetType sets the ICMP type field. 134 func (b ICMPv4) SetType(t ICMPv4Type) { b[0] = byte(t) } 135 136 // Code is the ICMP code field. Its meaning depends on the value of Type. 137 func (b ICMPv4) Code() ICMPv4Code { return ICMPv4Code(b[1]) } 138 139 // SetCode sets the ICMP code field. 140 func (b ICMPv4) SetCode(c ICMPv4Code) { b[1] = byte(c) } 141 142 // Pointer returns the pointer field in a Parameter Problem packet. 143 func (b ICMPv4) Pointer() byte { return b[icmpv4PointerOffset] } 144 145 // SetPointer sets the pointer field in a Parameter Problem packet. 146 func (b ICMPv4) SetPointer(c byte) { b[icmpv4PointerOffset] = c } 147 148 // Checksum is the ICMP checksum field. 149 func (b ICMPv4) Checksum() uint16 { 150 return binary.BigEndian.Uint16(b[icmpv4ChecksumOffset:]) 151 } 152 153 // SetChecksum sets the ICMP checksum field. 154 func (b ICMPv4) SetChecksum(cs uint16) { 155 checksum.Put(b[icmpv4ChecksumOffset:], cs) 156 } 157 158 // SourcePort implements Transport.SourcePort. 159 func (ICMPv4) SourcePort() uint16 { 160 return 0 161 } 162 163 // DestinationPort implements Transport.DestinationPort. 164 func (ICMPv4) DestinationPort() uint16 { 165 return 0 166 } 167 168 // SetSourcePort implements Transport.SetSourcePort. 169 func (ICMPv4) SetSourcePort(uint16) { 170 } 171 172 // SetDestinationPort implements Transport.SetDestinationPort. 173 func (ICMPv4) SetDestinationPort(uint16) { 174 } 175 176 // Payload implements Transport.Payload. 177 func (b ICMPv4) Payload() []byte { 178 return b[ICMPv4PayloadOffset:] 179 } 180 181 // MTU retrieves the MTU field from an ICMPv4 message. 182 func (b ICMPv4) MTU() uint16 { 183 return binary.BigEndian.Uint16(b[icmpv4MTUOffset:]) 184 } 185 186 // SetMTU sets the MTU field from an ICMPv4 message. 187 func (b ICMPv4) SetMTU(mtu uint16) { 188 binary.BigEndian.PutUint16(b[icmpv4MTUOffset:], mtu) 189 } 190 191 // Ident retrieves the Ident field from an ICMPv4 message. 192 func (b ICMPv4) Ident() uint16 { 193 return binary.BigEndian.Uint16(b[icmpv4IdentOffset:]) 194 } 195 196 // SetIdent sets the Ident field from an ICMPv4 message. 197 func (b ICMPv4) SetIdent(ident uint16) { 198 binary.BigEndian.PutUint16(b[icmpv4IdentOffset:], ident) 199 } 200 201 // SetIdentWithChecksumUpdate sets the Ident field and updates the checksum. 202 func (b ICMPv4) SetIdentWithChecksumUpdate(new uint16) { 203 old := b.Ident() 204 b.SetIdent(new) 205 b.SetChecksum(^checksumUpdate2ByteAlignedUint16(^b.Checksum(), old, new)) 206 } 207 208 // Sequence retrieves the Sequence field from an ICMPv4 message. 209 func (b ICMPv4) Sequence() uint16 { 210 return binary.BigEndian.Uint16(b[icmpv4SequenceOffset:]) 211 } 212 213 // SetSequence sets the Sequence field from an ICMPv4 message. 214 func (b ICMPv4) SetSequence(sequence uint16) { 215 binary.BigEndian.PutUint16(b[icmpv4SequenceOffset:], sequence) 216 } 217 218 // ICMPv4Checksum calculates the ICMP checksum over the provided ICMP header, 219 // and payload. 220 func ICMPv4Checksum(h ICMPv4, payloadCsum uint16) uint16 { 221 xsum := payloadCsum 222 223 // h[2:4] is the checksum itself, skip it to avoid checksumming the checksum. 224 xsum = checksum.Checksum(h[:2], xsum) 225 xsum = checksum.Checksum(h[4:], xsum) 226 227 return ^xsum 228 }