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