github.com/google/netstack@v0.0.0-20191123085552-55fcc16cd0eb/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/google/netstack/tcpip" 21 "github.com/google/netstack/tcpip/buffer" 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 // ICMPv4ProtocolNumber is the ICMP transport protocol number. 35 ICMPv4ProtocolNumber tcpip.TransportProtocolNumber = 1 36 37 // icmpv4ChecksumOffset is the offset of the checksum field 38 // in an ICMPv4 message. 39 icmpv4ChecksumOffset = 2 40 41 // icmpv4MTUOffset is the offset of the MTU field 42 // in a ICMPv4FragmentationNeeded message. 43 icmpv4MTUOffset = 6 44 45 // icmpv4IdentOffset is the offset of the ident field 46 // in a ICMPv4EchoRequest/Reply message. 47 icmpv4IdentOffset = 4 48 49 // icmpv4SequenceOffset is the offset of the sequence field 50 // in a ICMPv4EchoRequest/Reply message. 51 icmpv4SequenceOffset = 6 52 ) 53 54 // ICMPv4Type is the ICMP type field described in RFC 792. 55 type ICMPv4Type byte 56 57 // Typical values of ICMPv4Type defined in RFC 792. 58 const ( 59 ICMPv4EchoReply ICMPv4Type = 0 60 ICMPv4DstUnreachable ICMPv4Type = 3 61 ICMPv4SrcQuench ICMPv4Type = 4 62 ICMPv4Redirect ICMPv4Type = 5 63 ICMPv4Echo ICMPv4Type = 8 64 ICMPv4TimeExceeded ICMPv4Type = 11 65 ICMPv4ParamProblem ICMPv4Type = 12 66 ICMPv4Timestamp ICMPv4Type = 13 67 ICMPv4TimestampReply ICMPv4Type = 14 68 ICMPv4InfoRequest ICMPv4Type = 15 69 ICMPv4InfoReply ICMPv4Type = 16 70 ) 71 72 // Values for ICMP code as defined in RFC 792. 73 const ( 74 ICMPv4PortUnreachable = 3 75 ICMPv4FragmentationNeeded = 4 76 ) 77 78 // Type is the ICMP type field. 79 func (b ICMPv4) Type() ICMPv4Type { return ICMPv4Type(b[0]) } 80 81 // SetType sets the ICMP type field. 82 func (b ICMPv4) SetType(t ICMPv4Type) { b[0] = byte(t) } 83 84 // Code is the ICMP code field. Its meaning depends on the value of Type. 85 func (b ICMPv4) Code() byte { return b[1] } 86 87 // SetCode sets the ICMP code field. 88 func (b ICMPv4) SetCode(c byte) { b[1] = c } 89 90 // Checksum is the ICMP checksum field. 91 func (b ICMPv4) Checksum() uint16 { 92 return binary.BigEndian.Uint16(b[icmpv4ChecksumOffset:]) 93 } 94 95 // SetChecksum sets the ICMP checksum field. 96 func (b ICMPv4) SetChecksum(checksum uint16) { 97 binary.BigEndian.PutUint16(b[icmpv4ChecksumOffset:], checksum) 98 } 99 100 // SourcePort implements Transport.SourcePort. 101 func (ICMPv4) SourcePort() uint16 { 102 return 0 103 } 104 105 // DestinationPort implements Transport.DestinationPort. 106 func (ICMPv4) DestinationPort() uint16 { 107 return 0 108 } 109 110 // SetSourcePort implements Transport.SetSourcePort. 111 func (ICMPv4) SetSourcePort(uint16) { 112 } 113 114 // SetDestinationPort implements Transport.SetDestinationPort. 115 func (ICMPv4) SetDestinationPort(uint16) { 116 } 117 118 // Payload implements Transport.Payload. 119 func (b ICMPv4) Payload() []byte { 120 return b[ICMPv4PayloadOffset:] 121 } 122 123 // MTU retrieves the MTU field from an ICMPv4 message. 124 func (b ICMPv4) MTU() uint16 { 125 return binary.BigEndian.Uint16(b[icmpv4MTUOffset:]) 126 } 127 128 // SetMTU sets the MTU field from an ICMPv4 message. 129 func (b ICMPv4) SetMTU(mtu uint16) { 130 binary.BigEndian.PutUint16(b[icmpv4MTUOffset:], mtu) 131 } 132 133 // Ident retrieves the Ident field from an ICMPv4 message. 134 func (b ICMPv4) Ident() uint16 { 135 return binary.BigEndian.Uint16(b[icmpv4IdentOffset:]) 136 } 137 138 // SetIdent sets the Ident field from an ICMPv4 message. 139 func (b ICMPv4) SetIdent(ident uint16) { 140 binary.BigEndian.PutUint16(b[icmpv4IdentOffset:], ident) 141 } 142 143 // Sequence retrieves the Sequence field from an ICMPv4 message. 144 func (b ICMPv4) Sequence() uint16 { 145 return binary.BigEndian.Uint16(b[icmpv4SequenceOffset:]) 146 } 147 148 // SetSequence sets the Sequence field from an ICMPv4 message. 149 func (b ICMPv4) SetSequence(sequence uint16) { 150 binary.BigEndian.PutUint16(b[icmpv4SequenceOffset:], sequence) 151 } 152 153 // ICMPv4Checksum calculates the ICMP checksum over the provided ICMP header, 154 // and payload. 155 func ICMPv4Checksum(h ICMPv4, vv buffer.VectorisedView) uint16 { 156 // Calculate the IPv6 pseudo-header upper-layer checksum. 157 xsum := uint16(0) 158 for _, v := range vv.Views() { 159 xsum = Checksum(v, xsum) 160 } 161 162 // h[2:4] is the checksum itself, set it aside to avoid checksumming the checksum. 163 h2, h3 := h[2], h[3] 164 h[2], h[3] = 0, 0 165 xsum = ^Checksum(h, xsum) 166 h[2], h[3] = h2, h3 167 168 return xsum 169 }