github.com/google/netstack@v0.0.0-20191123085552-55fcc16cd0eb/tcpip/header/ipv6.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 "strings" 20 21 "github.com/google/netstack/tcpip" 22 ) 23 24 const ( 25 versTCFL = 0 26 // IPv6PayloadLenOffset is the offset of the PayloadLength field in 27 // IPv6 header. 28 IPv6PayloadLenOffset = 4 29 nextHdr = 6 30 hopLimit = 7 31 v6SrcAddr = 8 32 v6DstAddr = v6SrcAddr + IPv6AddressSize 33 ) 34 35 // IPv6Fields contains the fields of an IPv6 packet. It is used to describe the 36 // fields of a packet that needs to be encoded. 37 type IPv6Fields struct { 38 // TrafficClass is the "traffic class" field of an IPv6 packet. 39 TrafficClass uint8 40 41 // FlowLabel is the "flow label" field of an IPv6 packet. 42 FlowLabel uint32 43 44 // PayloadLength is the "payload length" field of an IPv6 packet. 45 PayloadLength uint16 46 47 // NextHeader is the "next header" field of an IPv6 packet. 48 NextHeader uint8 49 50 // HopLimit is the "hop limit" field of an IPv6 packet. 51 HopLimit uint8 52 53 // SrcAddr is the "source ip address" of an IPv6 packet. 54 SrcAddr tcpip.Address 55 56 // DstAddr is the "destination ip address" of an IPv6 packet. 57 DstAddr tcpip.Address 58 } 59 60 // IPv6 represents an ipv6 header stored in a byte array. 61 // Most of the methods of IPv6 access to the underlying slice without 62 // checking the boundaries and could panic because of 'index out of range'. 63 // Always call IsValid() to validate an instance of IPv6 before using other methods. 64 type IPv6 []byte 65 66 const ( 67 // IPv6MinimumSize is the minimum size of a valid IPv6 packet. 68 IPv6MinimumSize = 40 69 70 // IPv6AddressSize is the size, in bytes, of an IPv6 address. 71 IPv6AddressSize = 16 72 73 // IPv6ProtocolNumber is IPv6's network protocol number. 74 IPv6ProtocolNumber tcpip.NetworkProtocolNumber = 0x86dd 75 76 // IPv6Version is the version of the ipv6 protocol. 77 IPv6Version = 6 78 79 // IPv6AllNodesMulticastAddress is a link-local multicast group that 80 // all IPv6 nodes MUST join, as per RFC 4291, section 2.8. Packets 81 // destined to this address will reach all nodes on a link. 82 // 83 // The address is ff02::1. 84 IPv6AllNodesMulticastAddress tcpip.Address = "\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" 85 86 // IPv6MinimumMTU is the minimum MTU required by IPv6, per RFC 2460, 87 // section 5. 88 IPv6MinimumMTU = 1280 89 90 // IPv6Any is the non-routable IPv6 "any" meta address. It is also 91 // known as the unspecified address. 92 IPv6Any tcpip.Address = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 93 ) 94 95 // IPv6EmptySubnet is the empty IPv6 subnet. It may also be known as the 96 // catch-all or wildcard subnet. That is, all IPv6 addresses are considered to 97 // be contained within this subnet. 98 var IPv6EmptySubnet = func() tcpip.Subnet { 99 subnet, err := tcpip.NewSubnet(IPv6Any, tcpip.AddressMask(IPv6Any)) 100 if err != nil { 101 panic(err) 102 } 103 return subnet 104 }() 105 106 // IPv6LinkLocalPrefix is the prefix for IPv6 link-local addresses, as defined 107 // by RFC 4291 section 2.5.6. 108 // 109 // The prefix is fe80::/64 110 var IPv6LinkLocalPrefix = tcpip.AddressWithPrefix{ 111 Address: "\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 112 PrefixLen: 64, 113 } 114 115 // PayloadLength returns the value of the "payload length" field of the ipv6 116 // header. 117 func (b IPv6) PayloadLength() uint16 { 118 return binary.BigEndian.Uint16(b[IPv6PayloadLenOffset:]) 119 } 120 121 // HopLimit returns the value of the "hop limit" field of the ipv6 header. 122 func (b IPv6) HopLimit() uint8 { 123 return b[hopLimit] 124 } 125 126 // NextHeader returns the value of the "next header" field of the ipv6 header. 127 func (b IPv6) NextHeader() uint8 { 128 return b[nextHdr] 129 } 130 131 // TransportProtocol implements Network.TransportProtocol. 132 func (b IPv6) TransportProtocol() tcpip.TransportProtocolNumber { 133 return tcpip.TransportProtocolNumber(b.NextHeader()) 134 } 135 136 // Payload implements Network.Payload. 137 func (b IPv6) Payload() []byte { 138 return b[IPv6MinimumSize:][:b.PayloadLength()] 139 } 140 141 // SourceAddress returns the "source address" field of the ipv6 header. 142 func (b IPv6) SourceAddress() tcpip.Address { 143 return tcpip.Address(b[v6SrcAddr:][:IPv6AddressSize]) 144 } 145 146 // DestinationAddress returns the "destination address" field of the ipv6 147 // header. 148 func (b IPv6) DestinationAddress() tcpip.Address { 149 return tcpip.Address(b[v6DstAddr:][:IPv6AddressSize]) 150 } 151 152 // Checksum implements Network.Checksum. Given that IPv6 doesn't have a 153 // checksum, it just returns 0. 154 func (IPv6) Checksum() uint16 { 155 return 0 156 } 157 158 // TOS returns the "traffic class" and "flow label" fields of the ipv6 header. 159 func (b IPv6) TOS() (uint8, uint32) { 160 v := binary.BigEndian.Uint32(b[versTCFL:]) 161 return uint8(v >> 20), v & 0xfffff 162 } 163 164 // SetTOS sets the "traffic class" and "flow label" fields of the ipv6 header. 165 func (b IPv6) SetTOS(t uint8, l uint32) { 166 vtf := (6 << 28) | (uint32(t) << 20) | (l & 0xfffff) 167 binary.BigEndian.PutUint32(b[versTCFL:], vtf) 168 } 169 170 // SetPayloadLength sets the "payload length" field of the ipv6 header. 171 func (b IPv6) SetPayloadLength(payloadLength uint16) { 172 binary.BigEndian.PutUint16(b[IPv6PayloadLenOffset:], payloadLength) 173 } 174 175 // SetSourceAddress sets the "source address" field of the ipv6 header. 176 func (b IPv6) SetSourceAddress(addr tcpip.Address) { 177 copy(b[v6SrcAddr:][:IPv6AddressSize], addr) 178 } 179 180 // SetDestinationAddress sets the "destination address" field of the ipv6 181 // header. 182 func (b IPv6) SetDestinationAddress(addr tcpip.Address) { 183 copy(b[v6DstAddr:][:IPv6AddressSize], addr) 184 } 185 186 // SetNextHeader sets the value of the "next header" field of the ipv6 header. 187 func (b IPv6) SetNextHeader(v uint8) { 188 b[nextHdr] = v 189 } 190 191 // SetChecksum implements Network.SetChecksum. Given that IPv6 doesn't have a 192 // checksum, it is empty. 193 func (IPv6) SetChecksum(uint16) { 194 } 195 196 // Encode encodes all the fields of the ipv6 header. 197 func (b IPv6) Encode(i *IPv6Fields) { 198 b.SetTOS(i.TrafficClass, i.FlowLabel) 199 b.SetPayloadLength(i.PayloadLength) 200 b[nextHdr] = i.NextHeader 201 b[hopLimit] = i.HopLimit 202 b.SetSourceAddress(i.SrcAddr) 203 b.SetDestinationAddress(i.DstAddr) 204 } 205 206 // IsValid performs basic validation on the packet. 207 func (b IPv6) IsValid(pktSize int) bool { 208 if len(b) < IPv6MinimumSize { 209 return false 210 } 211 212 dlen := int(b.PayloadLength()) 213 if dlen > pktSize-IPv6MinimumSize { 214 return false 215 } 216 217 if IPVersion(b) != IPv6Version { 218 return false 219 } 220 221 return true 222 } 223 224 // IsV4MappedAddress determines if the provided address is an IPv4 mapped 225 // address by checking if its prefix is 0:0:0:0:0:ffff::/96. 226 func IsV4MappedAddress(addr tcpip.Address) bool { 227 if len(addr) != IPv6AddressSize { 228 return false 229 } 230 231 return strings.HasPrefix(string(addr), "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff") 232 } 233 234 // IsV6MulticastAddress determines if the provided address is an IPv6 235 // multicast address (anything starting with FF). 236 func IsV6MulticastAddress(addr tcpip.Address) bool { 237 if len(addr) != IPv6AddressSize { 238 return false 239 } 240 return addr[0] == 0xff 241 } 242 243 // IsV6UnicastAddress determines if the provided address is a valid IPv6 244 // unicast (and specified) address. That is, IsV6UnicastAddress returns 245 // true if addr contains IPv6AddressSize bytes, is not the unspecified 246 // address and is not a multicast address. 247 func IsV6UnicastAddress(addr tcpip.Address) bool { 248 if len(addr) != IPv6AddressSize { 249 return false 250 } 251 252 // Must not be unspecified 253 if addr == IPv6Any { 254 return false 255 } 256 257 // Return if not a multicast. 258 return addr[0] != 0xff 259 } 260 261 // SolicitedNodeAddr computes the solicited-node multicast address. This is 262 // used for NDP. Described in RFC 4291. The argument must be a full-length IPv6 263 // address. 264 func SolicitedNodeAddr(addr tcpip.Address) tcpip.Address { 265 const solicitedNodeMulticastPrefix = "\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff" 266 return solicitedNodeMulticastPrefix + addr[len(addr)-3:] 267 } 268 269 // LinkLocalAddr computes the default IPv6 link-local address from a link-layer 270 // (MAC) address. 271 func LinkLocalAddr(linkAddr tcpip.LinkAddress) tcpip.Address { 272 // Convert a 48-bit MAC to an EUI-64 and then prepend the link-local 273 // header, FE80::. 274 // 275 // The conversion is very nearly: 276 // aa:bb:cc:dd:ee:ff => FE80::Aabb:ccFF:FEdd:eeff 277 // Note the capital A. The conversion aa->Aa involves a bit flip. 278 lladdrb := [16]byte{ 279 0: 0xFE, 280 1: 0x80, 281 8: linkAddr[0] ^ 2, 282 9: linkAddr[1], 283 10: linkAddr[2], 284 11: 0xFF, 285 12: 0xFE, 286 13: linkAddr[3], 287 14: linkAddr[4], 288 15: linkAddr[5], 289 } 290 return tcpip.Address(lladdrb[:]) 291 } 292 293 // IsV6LinkLocalAddress determines if the provided address is an IPv6 294 // link-local address (fe80::/10). 295 func IsV6LinkLocalAddress(addr tcpip.Address) bool { 296 if len(addr) != IPv6AddressSize { 297 return false 298 } 299 return addr[0] == 0xfe && (addr[1]&0xc0) == 0x80 300 }