github.com/flowerwrong/netstack@v0.0.0-20191009141956-e5848263af28/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/FlowerWrong/netstack/tcpip" 21 "github.com/FlowerWrong/netstack/tcpip/buffer" 22 ) 23 24 // ICMPv6 represents an ICMPv6 header stored in a byte array. 25 type ICMPv6 []byte 26 27 const ( 28 // ICMPv6MinimumSize is the minimum size of a valid ICMP packet. 29 ICMPv6MinimumSize = 8 30 31 // ICMPv6PayloadOffset is the offset of the payload in an 32 // ICMP packet. 33 ICMPv6PayloadOffset = 8 34 35 // ICMPv6ProtocolNumber is the ICMP transport protocol number. 36 ICMPv6ProtocolNumber tcpip.TransportProtocolNumber = 58 37 38 // ICMPv6NeighborSolicitMinimumSize is the minimum size of a 39 // neighbor solicitation packet. 40 ICMPv6NeighborSolicitMinimumSize = ICMPv6MinimumSize + 16 41 42 // ICMPv6NeighborAdvertSize is size of a neighbor advertisement. 43 ICMPv6NeighborAdvertSize = 32 44 45 // ICMPv6EchoMinimumSize is the minimum size of a valid ICMP echo packet. 46 ICMPv6EchoMinimumSize = 8 47 48 // ICMPv6DstUnreachableMinimumSize is the minimum size of a valid ICMP 49 // destination unreachable packet. 50 ICMPv6DstUnreachableMinimumSize = ICMPv6MinimumSize 51 52 // ICMPv6PacketTooBigMinimumSize is the minimum size of a valid ICMP 53 // packet-too-big packet. 54 ICMPv6PacketTooBigMinimumSize = ICMPv6MinimumSize 55 56 // icmpv6ChecksumOffset is the offset of the checksum field 57 // in an ICMPv6 message. 58 icmpv6ChecksumOffset = 2 59 60 // icmpv6MTUOffset is the offset of the MTU field in an ICMPv6 61 // PacketTooBig message. 62 icmpv6MTUOffset = 4 63 64 // icmpv6IdentOffset is the offset of the ident field 65 // in a ICMPv6 Echo Request/Reply message. 66 icmpv6IdentOffset = 4 67 68 // icmpv6SequenceOffset is the offset of the sequence field 69 // in a ICMPv6 Echo Request/Reply message. 70 icmpv6SequenceOffset = 6 71 ) 72 73 // ICMPv6Type is the ICMP type field described in RFC 4443 and friends. 74 type ICMPv6Type byte 75 76 // Typical values of ICMPv6Type defined in RFC 4443. 77 const ( 78 ICMPv6DstUnreachable ICMPv6Type = 1 79 ICMPv6PacketTooBig ICMPv6Type = 2 80 ICMPv6TimeExceeded ICMPv6Type = 3 81 ICMPv6ParamProblem ICMPv6Type = 4 82 ICMPv6EchoRequest ICMPv6Type = 128 83 ICMPv6EchoReply ICMPv6Type = 129 84 85 // Neighbor Discovery Protocol (NDP) messages, see RFC 4861. 86 87 ICMPv6RouterSolicit ICMPv6Type = 133 88 ICMPv6RouterAdvert ICMPv6Type = 134 89 ICMPv6NeighborSolicit ICMPv6Type = 135 90 ICMPv6NeighborAdvert ICMPv6Type = 136 91 ICMPv6RedirectMsg ICMPv6Type = 137 92 ) 93 94 // Values for ICMP code as defined in RFC 4443. 95 const ( 96 ICMPv6PortUnreachable = 4 97 ) 98 99 // Type is the ICMP type field. 100 func (b ICMPv6) Type() ICMPv6Type { return ICMPv6Type(b[0]) } 101 102 // SetType sets the ICMP type field. 103 func (b ICMPv6) SetType(t ICMPv6Type) { b[0] = byte(t) } 104 105 // Code is the ICMP code field. Its meaning depends on the value of Type. 106 func (b ICMPv6) Code() byte { return b[1] } 107 108 // SetCode sets the ICMP code field. 109 func (b ICMPv6) SetCode(c byte) { b[1] = c } 110 111 // Checksum is the ICMP checksum field. 112 func (b ICMPv6) Checksum() uint16 { 113 return binary.BigEndian.Uint16(b[icmpv6ChecksumOffset:]) 114 } 115 116 // SetChecksum calculates and sets the ICMP checksum field. 117 func (b ICMPv6) SetChecksum(checksum uint16) { 118 binary.BigEndian.PutUint16(b[icmpv6ChecksumOffset:], checksum) 119 } 120 121 // SourcePort implements Transport.SourcePort. 122 func (ICMPv6) SourcePort() uint16 { 123 return 0 124 } 125 126 // DestinationPort implements Transport.DestinationPort. 127 func (ICMPv6) DestinationPort() uint16 { 128 return 0 129 } 130 131 // SetSourcePort implements Transport.SetSourcePort. 132 func (ICMPv6) SetSourcePort(uint16) { 133 } 134 135 // SetDestinationPort implements Transport.SetDestinationPort. 136 func (ICMPv6) SetDestinationPort(uint16) { 137 } 138 139 // MTU retrieves the MTU field from an ICMPv6 message. 140 func (b ICMPv6) MTU() uint32 { 141 return binary.BigEndian.Uint32(b[icmpv6MTUOffset:]) 142 } 143 144 // SetMTU sets the MTU field from an ICMPv6 message. 145 func (b ICMPv6) SetMTU(mtu uint32) { 146 binary.BigEndian.PutUint32(b[icmpv6MTUOffset:], mtu) 147 } 148 149 // Ident retrieves the Ident field from an ICMPv6 message. 150 func (b ICMPv6) Ident() uint16 { 151 return binary.BigEndian.Uint16(b[icmpv6IdentOffset:]) 152 } 153 154 // SetIdent sets the Ident field from an ICMPv6 message. 155 func (b ICMPv6) SetIdent(ident uint16) { 156 binary.BigEndian.PutUint16(b[icmpv6IdentOffset:], ident) 157 } 158 159 // Sequence retrieves the Sequence field from an ICMPv6 message. 160 func (b ICMPv6) Sequence() uint16 { 161 return binary.BigEndian.Uint16(b[icmpv6SequenceOffset:]) 162 } 163 164 // SetSequence sets the Sequence field from an ICMPv6 message. 165 func (b ICMPv6) SetSequence(sequence uint16) { 166 binary.BigEndian.PutUint16(b[icmpv6SequenceOffset:], sequence) 167 } 168 169 // Payload implements Transport.Payload. 170 func (b ICMPv6) Payload() []byte { 171 return b[ICMPv6PayloadOffset:] 172 } 173 174 // ICMPv6Checksum calculates the ICMP checksum over the provided ICMP header, 175 // IPv6 src/dst addresses and the payload. 176 func ICMPv6Checksum(h ICMPv6, src, dst tcpip.Address, vv buffer.VectorisedView) uint16 { 177 // Calculate the IPv6 pseudo-header upper-layer checksum. 178 xsum := Checksum([]byte(src), 0) 179 xsum = Checksum([]byte(dst), xsum) 180 var upperLayerLength [4]byte 181 binary.BigEndian.PutUint32(upperLayerLength[:], uint32(len(h)+vv.Size())) 182 xsum = Checksum(upperLayerLength[:], xsum) 183 xsum = Checksum([]byte{0, 0, 0, uint8(ICMPv6ProtocolNumber)}, xsum) 184 for _, v := range vv.Views() { 185 xsum = Checksum(v, xsum) 186 } 187 188 // h[2:4] is the checksum itself, set it aside to avoid checksumming the checksum. 189 h2, h3 := h[2], h[3] 190 h[2], h[3] = 0, 0 191 xsum = ^Checksum(h, xsum) 192 h[2], h[3] = h2, h3 193 194 return xsum 195 }