github.com/google/netstack@v0.0.0-20191123085552-55fcc16cd0eb/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/google/netstack/tcpip" 21 "github.com/google/netstack/tcpip/buffer" 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 // ICMPv6NeighborAdvertSize is size of a neighbor advertisement 53 // including the NDP Target Link Layer option for an Ethernet 54 // address. 55 ICMPv6NeighborAdvertSize = ICMPv6HeaderSize + NDPNAMinimumSize + ndpTargetEthernetLinkLayerAddressSize 56 57 // ICMPv6EchoMinimumSize is the minimum size of a valid ICMP echo packet. 58 ICMPv6EchoMinimumSize = 8 59 60 // ICMPv6DstUnreachableMinimumSize is the minimum size of a valid ICMP 61 // destination unreachable packet. 62 ICMPv6DstUnreachableMinimumSize = ICMPv6MinimumSize 63 64 // ICMPv6PacketTooBigMinimumSize is the minimum size of a valid ICMP 65 // packet-too-big packet. 66 ICMPv6PacketTooBigMinimumSize = ICMPv6MinimumSize 67 68 // icmpv6ChecksumOffset is the offset of the checksum field 69 // in an ICMPv6 message. 70 icmpv6ChecksumOffset = 2 71 72 // icmpv6MTUOffset is the offset of the MTU field in an ICMPv6 73 // PacketTooBig message. 74 icmpv6MTUOffset = 4 75 76 // icmpv6IdentOffset is the offset of the ident field 77 // in a ICMPv6 Echo Request/Reply message. 78 icmpv6IdentOffset = 4 79 80 // icmpv6SequenceOffset is the offset of the sequence field 81 // in a ICMPv6 Echo Request/Reply message. 82 icmpv6SequenceOffset = 6 83 84 // NDPHopLimit is the expected IP hop limit value of 255 for received 85 // NDP packets, as per RFC 4861 sections 4.1 - 4.5, 6.1.1, 6.1.2, 7.1.1, 86 // 7.1.2 and 8.1. If the hop limit value is not 255, nodes MUST silently 87 // drop the NDP packet. All outgoing NDP packets must use this value for 88 // its IP hop limit field. 89 NDPHopLimit = 255 90 ) 91 92 // ICMPv6Type is the ICMP type field described in RFC 4443 and friends. 93 type ICMPv6Type byte 94 95 // Typical values of ICMPv6Type defined in RFC 4443. 96 const ( 97 ICMPv6DstUnreachable ICMPv6Type = 1 98 ICMPv6PacketTooBig ICMPv6Type = 2 99 ICMPv6TimeExceeded ICMPv6Type = 3 100 ICMPv6ParamProblem ICMPv6Type = 4 101 ICMPv6EchoRequest ICMPv6Type = 128 102 ICMPv6EchoReply ICMPv6Type = 129 103 104 // Neighbor Discovery Protocol (NDP) messages, see RFC 4861. 105 106 ICMPv6RouterSolicit ICMPv6Type = 133 107 ICMPv6RouterAdvert ICMPv6Type = 134 108 ICMPv6NeighborSolicit ICMPv6Type = 135 109 ICMPv6NeighborAdvert ICMPv6Type = 136 110 ICMPv6RedirectMsg ICMPv6Type = 137 111 ) 112 113 // Values for ICMP code as defined in RFC 4443. 114 const ( 115 ICMPv6PortUnreachable = 4 116 ) 117 118 // Type is the ICMP type field. 119 func (b ICMPv6) Type() ICMPv6Type { return ICMPv6Type(b[0]) } 120 121 // SetType sets the ICMP type field. 122 func (b ICMPv6) SetType(t ICMPv6Type) { b[0] = byte(t) } 123 124 // Code is the ICMP code field. Its meaning depends on the value of Type. 125 func (b ICMPv6) Code() byte { return b[1] } 126 127 // SetCode sets the ICMP code field. 128 func (b ICMPv6) SetCode(c byte) { b[1] = c } 129 130 // Checksum is the ICMP checksum field. 131 func (b ICMPv6) Checksum() uint16 { 132 return binary.BigEndian.Uint16(b[icmpv6ChecksumOffset:]) 133 } 134 135 // SetChecksum sets the ICMP checksum field. 136 func (b ICMPv6) SetChecksum(checksum uint16) { 137 binary.BigEndian.PutUint16(b[icmpv6ChecksumOffset:], checksum) 138 } 139 140 // SourcePort implements Transport.SourcePort. 141 func (ICMPv6) SourcePort() uint16 { 142 return 0 143 } 144 145 // DestinationPort implements Transport.DestinationPort. 146 func (ICMPv6) DestinationPort() uint16 { 147 return 0 148 } 149 150 // SetSourcePort implements Transport.SetSourcePort. 151 func (ICMPv6) SetSourcePort(uint16) { 152 } 153 154 // SetDestinationPort implements Transport.SetDestinationPort. 155 func (ICMPv6) SetDestinationPort(uint16) { 156 } 157 158 // MTU retrieves the MTU field from an ICMPv6 message. 159 func (b ICMPv6) MTU() uint32 { 160 return binary.BigEndian.Uint32(b[icmpv6MTUOffset:]) 161 } 162 163 // SetMTU sets the MTU field from an ICMPv6 message. 164 func (b ICMPv6) SetMTU(mtu uint32) { 165 binary.BigEndian.PutUint32(b[icmpv6MTUOffset:], mtu) 166 } 167 168 // Ident retrieves the Ident field from an ICMPv6 message. 169 func (b ICMPv6) Ident() uint16 { 170 return binary.BigEndian.Uint16(b[icmpv6IdentOffset:]) 171 } 172 173 // SetIdent sets the Ident field from an ICMPv6 message. 174 func (b ICMPv6) SetIdent(ident uint16) { 175 binary.BigEndian.PutUint16(b[icmpv6IdentOffset:], ident) 176 } 177 178 // Sequence retrieves the Sequence field from an ICMPv6 message. 179 func (b ICMPv6) Sequence() uint16 { 180 return binary.BigEndian.Uint16(b[icmpv6SequenceOffset:]) 181 } 182 183 // SetSequence sets the Sequence field from an ICMPv6 message. 184 func (b ICMPv6) SetSequence(sequence uint16) { 185 binary.BigEndian.PutUint16(b[icmpv6SequenceOffset:], sequence) 186 } 187 188 // NDPPayload returns the NDP payload buffer. That is, it returns the ICMPv6 189 // packet's message body as defined by RFC 4443 section 2.1; the portion of the 190 // ICMPv6 buffer after the first ICMPv6HeaderSize bytes. 191 func (b ICMPv6) NDPPayload() []byte { 192 return b[ICMPv6HeaderSize:] 193 } 194 195 // Payload implements Transport.Payload. 196 func (b ICMPv6) Payload() []byte { 197 return b[ICMPv6PayloadOffset:] 198 } 199 200 // ICMPv6Checksum calculates the ICMP checksum over the provided ICMPv6 header, 201 // IPv6 src/dst addresses and the payload. 202 func ICMPv6Checksum(h ICMPv6, src, dst tcpip.Address, vv buffer.VectorisedView) uint16 { 203 // Calculate the IPv6 pseudo-header upper-layer checksum. 204 xsum := Checksum([]byte(src), 0) 205 xsum = Checksum([]byte(dst), xsum) 206 var upperLayerLength [4]byte 207 binary.BigEndian.PutUint32(upperLayerLength[:], uint32(len(h)+vv.Size())) 208 xsum = Checksum(upperLayerLength[:], xsum) 209 xsum = Checksum([]byte{0, 0, 0, uint8(ICMPv6ProtocolNumber)}, xsum) 210 for _, v := range vv.Views() { 211 xsum = Checksum(v, xsum) 212 } 213 214 // h[2:4] is the checksum itself, set it aside to avoid checksumming the checksum. 215 h2, h3 := h[2], h[3] 216 h[2], h[3] = 0, 0 217 xsum = ^Checksum(h, xsum) 218 h[2], h[3] = h2, h3 219 220 return xsum 221 }