gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/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 "crypto/sha256" 19 "encoding/binary" 20 "fmt" 21 22 "gvisor.dev/gvisor/pkg/tcpip" 23 ) 24 25 const ( 26 versTCFL = 0 27 // IPv6PayloadLenOffset is the offset of the PayloadLength field in 28 // IPv6 header. 29 IPv6PayloadLenOffset = 4 30 // IPv6NextHeaderOffset is the offset of the NextHeader field in 31 // IPv6 header. 32 IPv6NextHeaderOffset = 6 33 hopLimit = 7 34 v6SrcAddr = 8 35 v6DstAddr = v6SrcAddr + IPv6AddressSize 36 37 // IPv6FixedHeaderSize is the size of the fixed header. 38 IPv6FixedHeaderSize = v6DstAddr + IPv6AddressSize 39 ) 40 41 // IPv6Fields contains the fields of an IPv6 packet. It is used to describe the 42 // fields of a packet that needs to be encoded. 43 type IPv6Fields struct { 44 // TrafficClass is the "traffic class" field of an IPv6 packet. 45 TrafficClass uint8 46 47 // FlowLabel is the "flow label" field of an IPv6 packet. 48 FlowLabel uint32 49 50 // PayloadLength is the "payload length" field of an IPv6 packet, including 51 // the length of all extension headers. 52 PayloadLength uint16 53 54 // TransportProtocol is the transport layer protocol number. Serialized in the 55 // last "next header" field of the IPv6 header + extension headers. 56 TransportProtocol tcpip.TransportProtocolNumber 57 58 // HopLimit is the "Hop Limit" field of an IPv6 packet. 59 HopLimit uint8 60 61 // SrcAddr is the "source ip address" of an IPv6 packet. 62 SrcAddr tcpip.Address 63 64 // DstAddr is the "destination ip address" of an IPv6 packet. 65 DstAddr tcpip.Address 66 67 // ExtensionHeaders are the extension headers following the IPv6 header. 68 ExtensionHeaders IPv6ExtHdrSerializer 69 } 70 71 // IPv6 represents an ipv6 header stored in a byte array. 72 // Most of the methods of IPv6 access to the underlying slice without 73 // checking the boundaries and could panic because of 'index out of range'. 74 // Always call IsValid() to validate an instance of IPv6 before using other methods. 75 type IPv6 []byte 76 77 const ( 78 // IPv6MinimumSize is the minimum size of a valid IPv6 packet. 79 IPv6MinimumSize = IPv6FixedHeaderSize 80 81 // IPv6AddressSize is the size, in bytes, of an IPv6 address. 82 IPv6AddressSize = 16 83 84 // IPv6AddressSizeBits is the size, in bits, of an IPv6 address. 85 IPv6AddressSizeBits = 128 86 87 // IPv6MaximumPayloadSize is the maximum size of a valid IPv6 payload per 88 // RFC 8200 Section 4.5. 89 IPv6MaximumPayloadSize = 65535 90 91 // IPv6ProtocolNumber is IPv6's network protocol number. 92 IPv6ProtocolNumber tcpip.NetworkProtocolNumber = 0x86dd 93 94 // IPv6Version is the version of the ipv6 protocol. 95 IPv6Version = 6 96 97 // IIDSize is the size of an interface identifier (IID), in bytes, as 98 // defined by RFC 4291 section 2.5.1. 99 IIDSize = 8 100 101 // IPv6MinimumMTU is the minimum MTU required by IPv6, per RFC 8200, 102 // section 5: 103 // IPv6 requires that every link in the Internet have an MTU of 1280 octets 104 // or greater. This is known as the IPv6 minimum link MTU. 105 IPv6MinimumMTU = 1280 106 107 // IIDOffsetInIPv6Address is the offset, in bytes, from the start 108 // of an IPv6 address to the beginning of the interface identifier 109 // (IID) for auto-generated addresses. That is, all bytes before 110 // the IIDOffsetInIPv6Address-th byte are the prefix bytes, and all 111 // bytes including and after the IIDOffsetInIPv6Address-th byte are 112 // for the IID. 113 IIDOffsetInIPv6Address = 8 114 115 // OpaqueIIDSecretKeyMinBytes is the recommended minimum number of bytes 116 // for the secret key used to generate an opaque interface identifier as 117 // outlined by RFC 7217. 118 OpaqueIIDSecretKeyMinBytes = 16 119 120 // ipv6MulticastAddressScopeByteIdx is the byte where the scope (scop) field 121 // is located within a multicast IPv6 address, as per RFC 4291 section 2.7. 122 ipv6MulticastAddressScopeByteIdx = 1 123 124 // ipv6MulticastAddressScopeMask is the mask for the scope (scop) field, 125 // within the byte holding the field, as per RFC 4291 section 2.7. 126 ipv6MulticastAddressScopeMask = 0xF 127 ) 128 129 var ( 130 // IPv6AllNodesMulticastAddress is a link-local multicast group that 131 // all IPv6 nodes MUST join, as per RFC 4291, section 2.8. Packets 132 // destined to this address will reach all nodes on a link. 133 // 134 // The address is ff02::1. 135 IPv6AllNodesMulticastAddress = tcpip.AddrFrom16([16]byte{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}) 136 137 // IPv6AllRoutersInterfaceLocalMulticastAddress is an interface-local 138 // multicast group that all IPv6 routers MUST join, as per RFC 4291, section 139 // 2.8. Packets destined to this address will reach the router on an 140 // interface. 141 // 142 // The address is ff01::2. 143 IPv6AllRoutersInterfaceLocalMulticastAddress = tcpip.AddrFrom16([16]byte{0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}) 144 145 // IPv6AllRoutersLinkLocalMulticastAddress is a link-local multicast group 146 // that all IPv6 routers MUST join, as per RFC 4291, section 2.8. Packets 147 // destined to this address will reach all routers on a link. 148 // 149 // The address is ff02::2. 150 IPv6AllRoutersLinkLocalMulticastAddress = tcpip.AddrFrom16([16]byte{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}) 151 152 // IPv6AllRoutersSiteLocalMulticastAddress is a site-local multicast group 153 // that all IPv6 routers MUST join, as per RFC 4291, section 2.8. Packets 154 // destined to this address will reach all routers in a site. 155 // 156 // The address is ff05::2. 157 IPv6AllRoutersSiteLocalMulticastAddress = tcpip.AddrFrom16([16]byte{0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}) 158 159 // IPv6Loopback is the IPv6 Loopback address. 160 IPv6Loopback = tcpip.AddrFrom16([16]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}) 161 162 // IPv6Any is the non-routable IPv6 "any" meta address. It is also 163 // known as the unspecified address. 164 IPv6Any = tcpip.AddrFrom16([16]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) 165 ) 166 167 // IPv6EmptySubnet is the empty IPv6 subnet. It may also be known as the 168 // catch-all or wildcard subnet. That is, all IPv6 addresses are considered to 169 // be contained within this subnet. 170 var IPv6EmptySubnet = tcpip.AddressWithPrefix{ 171 Address: IPv6Any, 172 PrefixLen: 0, 173 }.Subnet() 174 175 // IPv4MappedIPv6Subnet is the prefix for an IPv4 mapped IPv6 address as defined 176 // by RFC 4291 section 2.5.5. 177 var IPv4MappedIPv6Subnet = tcpip.AddressWithPrefix{ 178 Address: tcpip.AddrFrom16([16]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}), 179 PrefixLen: 96, 180 }.Subnet() 181 182 // IPv6LinkLocalPrefix is the prefix for IPv6 link-local addresses, as defined 183 // by RFC 4291 section 2.5.6. 184 // 185 // The prefix is fe80::/64 186 var IPv6LinkLocalPrefix = tcpip.AddressWithPrefix{ 187 Address: tcpip.AddrFrom16([16]byte{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), 188 PrefixLen: 64, 189 } 190 191 // PayloadLength returns the value of the "payload length" field of the ipv6 192 // header. 193 func (b IPv6) PayloadLength() uint16 { 194 return binary.BigEndian.Uint16(b[IPv6PayloadLenOffset:]) 195 } 196 197 // HopLimit returns the value of the "Hop Limit" field of the ipv6 header. 198 func (b IPv6) HopLimit() uint8 { 199 return b[hopLimit] 200 } 201 202 // NextHeader returns the value of the "next header" field of the ipv6 header. 203 func (b IPv6) NextHeader() uint8 { 204 return b[IPv6NextHeaderOffset] 205 } 206 207 // TransportProtocol implements Network.TransportProtocol. 208 func (b IPv6) TransportProtocol() tcpip.TransportProtocolNumber { 209 return tcpip.TransportProtocolNumber(b.NextHeader()) 210 } 211 212 // Payload implements Network.Payload. 213 func (b IPv6) Payload() []byte { 214 return b[IPv6MinimumSize:][:b.PayloadLength()] 215 } 216 217 // SourceAddress returns the "source address" field of the ipv6 header. 218 func (b IPv6) SourceAddress() tcpip.Address { 219 return tcpip.AddrFrom16([16]byte(b[v6SrcAddr:][:IPv6AddressSize])) 220 } 221 222 // DestinationAddress returns the "destination address" field of the ipv6 223 // header. 224 func (b IPv6) DestinationAddress() tcpip.Address { 225 return tcpip.AddrFrom16([16]byte(b[v6DstAddr:][:IPv6AddressSize])) 226 } 227 228 // SourceAddressSlice returns the "source address" field of the ipv6 header as a 229 // byte slice. 230 func (b IPv6) SourceAddressSlice() []byte { 231 return []byte(b[v6SrcAddr:][:IPv6AddressSize]) 232 } 233 234 // DestinationAddressSlice returns the "destination address" field of the ipv6 235 // header as a byte slice. 236 func (b IPv6) DestinationAddressSlice() []byte { 237 return []byte(b[v6DstAddr:][:IPv6AddressSize]) 238 } 239 240 // Checksum implements Network.Checksum. Given that IPv6 doesn't have a 241 // checksum, it just returns 0. 242 func (IPv6) Checksum() uint16 { 243 return 0 244 } 245 246 // TOS returns the "traffic class" and "flow label" fields of the ipv6 header. 247 func (b IPv6) TOS() (uint8, uint32) { 248 v := binary.BigEndian.Uint32(b[versTCFL:]) 249 return uint8(v >> 20), v & 0xfffff 250 } 251 252 // SetTOS sets the "traffic class" and "flow label" fields of the ipv6 header. 253 func (b IPv6) SetTOS(t uint8, l uint32) { 254 vtf := (6 << 28) | (uint32(t) << 20) | (l & 0xfffff) 255 binary.BigEndian.PutUint32(b[versTCFL:], vtf) 256 } 257 258 // SetPayloadLength sets the "payload length" field of the ipv6 header. 259 func (b IPv6) SetPayloadLength(payloadLength uint16) { 260 binary.BigEndian.PutUint16(b[IPv6PayloadLenOffset:], payloadLength) 261 } 262 263 // SetSourceAddress sets the "source address" field of the ipv6 header. 264 func (b IPv6) SetSourceAddress(addr tcpip.Address) { 265 copy(b[v6SrcAddr:][:IPv6AddressSize], addr.AsSlice()) 266 } 267 268 // SetDestinationAddress sets the "destination address" field of the ipv6 269 // header. 270 func (b IPv6) SetDestinationAddress(addr tcpip.Address) { 271 copy(b[v6DstAddr:][:IPv6AddressSize], addr.AsSlice()) 272 } 273 274 // SetHopLimit sets the value of the "Hop Limit" field. 275 func (b IPv6) SetHopLimit(v uint8) { 276 b[hopLimit] = v 277 } 278 279 // SetNextHeader sets the value of the "next header" field of the ipv6 header. 280 func (b IPv6) SetNextHeader(v uint8) { 281 b[IPv6NextHeaderOffset] = v 282 } 283 284 // SetChecksum implements Network.SetChecksum. Given that IPv6 doesn't have a 285 // checksum, it is empty. 286 func (IPv6) SetChecksum(uint16) { 287 } 288 289 // Encode encodes all the fields of the ipv6 header. 290 func (b IPv6) Encode(i *IPv6Fields) { 291 extHdr := b[IPv6MinimumSize:] 292 b.SetTOS(i.TrafficClass, i.FlowLabel) 293 b.SetPayloadLength(i.PayloadLength) 294 b[hopLimit] = i.HopLimit 295 b.SetSourceAddress(i.SrcAddr) 296 b.SetDestinationAddress(i.DstAddr) 297 nextHeader, _ := i.ExtensionHeaders.Serialize(i.TransportProtocol, extHdr) 298 b[IPv6NextHeaderOffset] = nextHeader 299 } 300 301 // IsValid performs basic validation on the packet. 302 func (b IPv6) IsValid(pktSize int) bool { 303 if len(b) < IPv6MinimumSize { 304 return false 305 } 306 307 dlen := int(b.PayloadLength()) 308 if dlen > pktSize-IPv6MinimumSize { 309 return false 310 } 311 312 if IPVersion(b) != IPv6Version { 313 return false 314 } 315 316 return true 317 } 318 319 // IsV4MappedAddress determines if the provided address is an IPv4 mapped 320 // address by checking if its prefix is 0:0:0:0:0:ffff::/96. 321 func IsV4MappedAddress(addr tcpip.Address) bool { 322 if addr.BitLen() != IPv6AddressSizeBits { 323 return false 324 } 325 326 return IPv4MappedIPv6Subnet.Contains(addr) 327 } 328 329 // IsV6MulticastAddress determines if the provided address is an IPv6 330 // multicast address (anything starting with FF). 331 func IsV6MulticastAddress(addr tcpip.Address) bool { 332 if addr.BitLen() != IPv6AddressSizeBits { 333 return false 334 } 335 return addr.As16()[0] == 0xff 336 } 337 338 // IsV6UnicastAddress determines if the provided address is a valid IPv6 339 // unicast (and specified) address. That is, IsV6UnicastAddress returns 340 // true if addr contains IPv6AddressSize bytes, is not the unspecified 341 // address and is not a multicast address. 342 func IsV6UnicastAddress(addr tcpip.Address) bool { 343 if addr.BitLen() != IPv6AddressSizeBits { 344 return false 345 } 346 347 // Must not be unspecified 348 if addr == IPv6Any { 349 return false 350 } 351 352 // Return if not a multicast. 353 return addr.As16()[0] != 0xff 354 } 355 356 var solicitedNodeMulticastPrefix = [13]byte{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff} 357 358 // SolicitedNodeAddr computes the solicited-node multicast address. This is 359 // used for NDP. Described in RFC 4291. The argument must be a full-length IPv6 360 // address. 361 func SolicitedNodeAddr(addr tcpip.Address) tcpip.Address { 362 addrBytes := addr.As16() 363 return tcpip.AddrFrom16([16]byte(append(solicitedNodeMulticastPrefix[:], addrBytes[len(addrBytes)-3:]...))) 364 } 365 366 // IsSolicitedNodeAddr determines whether the address is a solicited-node 367 // multicast address. 368 func IsSolicitedNodeAddr(addr tcpip.Address) bool { 369 addrBytes := addr.As16() 370 return solicitedNodeMulticastPrefix == [13]byte(addrBytes[:len(addrBytes)-3]) 371 } 372 373 // EthernetAdddressToModifiedEUI64IntoBuf populates buf with a modified EUI-64 374 // from a 48-bit Ethernet/MAC address, as per RFC 4291 section 2.5.1. 375 // 376 // buf MUST be at least 8 bytes. 377 func EthernetAdddressToModifiedEUI64IntoBuf(linkAddr tcpip.LinkAddress, buf []byte) { 378 buf[0] = linkAddr[0] ^ 2 379 buf[1] = linkAddr[1] 380 buf[2] = linkAddr[2] 381 buf[3] = 0xFF 382 buf[4] = 0xFE 383 buf[5] = linkAddr[3] 384 buf[6] = linkAddr[4] 385 buf[7] = linkAddr[5] 386 } 387 388 // EthernetAddressToModifiedEUI64 computes a modified EUI-64 from a 48-bit 389 // Ethernet/MAC address, as per RFC 4291 section 2.5.1. 390 func EthernetAddressToModifiedEUI64(linkAddr tcpip.LinkAddress) [IIDSize]byte { 391 var buf [IIDSize]byte 392 EthernetAdddressToModifiedEUI64IntoBuf(linkAddr, buf[:]) 393 return buf 394 } 395 396 // LinkLocalAddr computes the default IPv6 link-local address from a link-layer 397 // (MAC) address. 398 func LinkLocalAddr(linkAddr tcpip.LinkAddress) tcpip.Address { 399 // Convert a 48-bit MAC to a modified EUI-64 and then prepend the 400 // link-local header, FE80::. 401 // 402 // The conversion is very nearly: 403 // aa:bb:cc:dd:ee:ff => FE80::Aabb:ccFF:FEdd:eeff 404 // Note the capital A. The conversion aa->Aa involves a bit flip. 405 lladdrb := [IPv6AddressSize]byte{ 406 0: 0xFE, 407 1: 0x80, 408 } 409 EthernetAdddressToModifiedEUI64IntoBuf(linkAddr, lladdrb[IIDOffsetInIPv6Address:]) 410 return tcpip.AddrFrom16(lladdrb) 411 } 412 413 // IsV6LinkLocalUnicastAddress returns true iff the provided address is an IPv6 414 // link-local unicast address, as defined by RFC 4291 section 2.5.6. 415 func IsV6LinkLocalUnicastAddress(addr tcpip.Address) bool { 416 if addr.BitLen() != IPv6AddressSizeBits { 417 return false 418 } 419 addrBytes := addr.As16() 420 return addrBytes[0] == 0xfe && (addrBytes[1]&0xc0) == 0x80 421 } 422 423 // IsV6LoopbackAddress returns true iff the provided address is an IPv6 loopback 424 // address, as defined by RFC 4291 section 2.5.3. 425 func IsV6LoopbackAddress(addr tcpip.Address) bool { 426 return addr == IPv6Loopback 427 } 428 429 // IsV6LinkLocalMulticastAddress returns true iff the provided address is an 430 // IPv6 link-local multicast address, as defined by RFC 4291 section 2.7. 431 func IsV6LinkLocalMulticastAddress(addr tcpip.Address) bool { 432 return IsV6MulticastAddress(addr) && V6MulticastScope(addr) == IPv6LinkLocalMulticastScope 433 } 434 435 // AppendOpaqueInterfaceIdentifier appends a 64 bit opaque interface identifier 436 // (IID) to buf as outlined by RFC 7217 and returns the extended buffer. 437 // 438 // The opaque IID is generated from the cryptographic hash of the concatenation 439 // of the prefix, NIC's name, DAD counter (DAD retry counter) and the secret 440 // key. The secret key SHOULD be at least OpaqueIIDSecretKeyMinBytes bytes and 441 // MUST be generated to a pseudo-random number. See RFC 4086 for randomness 442 // requirements for security. 443 // 444 // If buf has enough capacity for the IID (IIDSize bytes), a new underlying 445 // array for the buffer will not be allocated. 446 func AppendOpaqueInterfaceIdentifier(buf []byte, prefix tcpip.Subnet, nicName string, dadCounter uint8, secretKey []byte) []byte { 447 // As per RFC 7217 section 5, the opaque identifier can be generated as a 448 // cryptographic hash of the concatenation of each of the function parameters. 449 // Note, we omit the optional Network_ID field. 450 h := sha256.New() 451 // h.Write never returns an error. 452 prefixID := prefix.ID() 453 h.Write([]byte(prefixID.AsSlice()[:IIDOffsetInIPv6Address])) 454 h.Write([]byte(nicName)) 455 h.Write([]byte{dadCounter}) 456 h.Write(secretKey) 457 458 var sumBuf [sha256.Size]byte 459 sum := h.Sum(sumBuf[:0]) 460 461 return append(buf, sum[:IIDSize]...) 462 } 463 464 // LinkLocalAddrWithOpaqueIID computes the default IPv6 link-local address with 465 // an opaque IID. 466 func LinkLocalAddrWithOpaqueIID(nicName string, dadCounter uint8, secretKey []byte) tcpip.Address { 467 lladdrb := [IPv6AddressSize]byte{ 468 0: 0xFE, 469 1: 0x80, 470 } 471 472 return tcpip.AddrFrom16([16]byte(AppendOpaqueInterfaceIdentifier(lladdrb[:IIDOffsetInIPv6Address], IPv6LinkLocalPrefix.Subnet(), nicName, dadCounter, secretKey))) 473 } 474 475 // IPv6AddressScope is the scope of an IPv6 address. 476 type IPv6AddressScope int 477 478 const ( 479 // LinkLocalScope indicates a link-local address. 480 LinkLocalScope IPv6AddressScope = iota 481 482 // GlobalScope indicates a global address. 483 GlobalScope 484 ) 485 486 // ScopeForIPv6Address returns the scope for an IPv6 address. 487 func ScopeForIPv6Address(addr tcpip.Address) (IPv6AddressScope, tcpip.Error) { 488 if addr.BitLen() != IPv6AddressSizeBits { 489 return GlobalScope, &tcpip.ErrBadAddress{} 490 } 491 492 switch { 493 case IsV6LinkLocalMulticastAddress(addr): 494 return LinkLocalScope, nil 495 496 case IsV6LinkLocalUnicastAddress(addr): 497 return LinkLocalScope, nil 498 499 default: 500 return GlobalScope, nil 501 } 502 } 503 504 // InitialTempIID generates the initial temporary IID history value to generate 505 // temporary SLAAC addresses with. 506 // 507 // Panics if initialTempIIDHistory is not at least IIDSize bytes. 508 func InitialTempIID(initialTempIIDHistory []byte, seed []byte, nicID tcpip.NICID) { 509 h := sha256.New() 510 // h.Write never returns an error. 511 h.Write(seed) 512 var nicIDBuf [4]byte 513 binary.BigEndian.PutUint32(nicIDBuf[:], uint32(nicID)) 514 h.Write(nicIDBuf[:]) 515 516 var sumBuf [sha256.Size]byte 517 sum := h.Sum(sumBuf[:0]) 518 519 if n := copy(initialTempIIDHistory, sum[sha256.Size-IIDSize:]); n != IIDSize { 520 panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, IIDSize)) 521 } 522 } 523 524 // GenerateTempIPv6SLAACAddr generates a temporary SLAAC IPv6 address for an 525 // associated stable/permanent SLAAC address. 526 // 527 // GenerateTempIPv6SLAACAddr will update the temporary IID history value to be 528 // used when generating a new temporary IID. 529 // 530 // Panics if tempIIDHistory is not at least IIDSize bytes. 531 func GenerateTempIPv6SLAACAddr(tempIIDHistory []byte, stableAddr tcpip.Address) tcpip.AddressWithPrefix { 532 addrBytes := stableAddr.As16() 533 h := sha256.New() 534 h.Write(tempIIDHistory) 535 h.Write(addrBytes[IIDOffsetInIPv6Address:]) 536 var sumBuf [sha256.Size]byte 537 sum := h.Sum(sumBuf[:0]) 538 539 // The rightmost 64 bits of sum are saved for the next iteration. 540 if n := copy(tempIIDHistory, sum[sha256.Size-IIDSize:]); n != IIDSize { 541 panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, IIDSize)) 542 } 543 544 // The leftmost 64 bits of sum is used as the IID. 545 if n := copy(addrBytes[IIDOffsetInIPv6Address:], sum); n != IIDSize { 546 panic(fmt.Sprintf("copied %d IID bytes, expected %d bytes", n, IIDSize)) 547 } 548 549 return tcpip.AddressWithPrefix{ 550 Address: tcpip.AddrFrom16(addrBytes), 551 PrefixLen: IIDOffsetInIPv6Address * 8, 552 } 553 } 554 555 // IPv6MulticastScope is the scope of a multicast IPv6 address, as defined by 556 // RFC 7346 section 2. 557 type IPv6MulticastScope uint8 558 559 // The various values for IPv6 multicast scopes, as per RFC 7346 section 2: 560 // 561 // +------+--------------------------+-------------------------+ 562 // | scop | NAME | REFERENCE | 563 // +------+--------------------------+-------------------------+ 564 // | 0 | Reserved | [RFC4291], RFC 7346 | 565 // | 1 | Interface-Local scope | [RFC4291], RFC 7346 | 566 // | 2 | Link-Local scope | [RFC4291], RFC 7346 | 567 // | 3 | Realm-Local scope | [RFC4291], RFC 7346 | 568 // | 4 | Admin-Local scope | [RFC4291], RFC 7346 | 569 // | 5 | Site-Local scope | [RFC4291], RFC 7346 | 570 // | 6 | Unassigned | | 571 // | 7 | Unassigned | | 572 // | 8 | Organization-Local scope | [RFC4291], RFC 7346 | 573 // | 9 | Unassigned | | 574 // | A | Unassigned | | 575 // | B | Unassigned | | 576 // | C | Unassigned | | 577 // | D | Unassigned | | 578 // | E | Global scope | [RFC4291], RFC 7346 | 579 // | F | Reserved | [RFC4291], RFC 7346 | 580 // +------+--------------------------+-------------------------+ 581 const ( 582 IPv6Reserved0MulticastScope = IPv6MulticastScope(0x0) 583 IPv6InterfaceLocalMulticastScope = IPv6MulticastScope(0x1) 584 IPv6LinkLocalMulticastScope = IPv6MulticastScope(0x2) 585 IPv6RealmLocalMulticastScope = IPv6MulticastScope(0x3) 586 IPv6AdminLocalMulticastScope = IPv6MulticastScope(0x4) 587 IPv6SiteLocalMulticastScope = IPv6MulticastScope(0x5) 588 IPv6OrganizationLocalMulticastScope = IPv6MulticastScope(0x8) 589 IPv6GlobalMulticastScope = IPv6MulticastScope(0xE) 590 IPv6ReservedFMulticastScope = IPv6MulticastScope(0xF) 591 ) 592 593 // V6MulticastScope returns the scope of a multicast address. 594 func V6MulticastScope(addr tcpip.Address) IPv6MulticastScope { 595 addrBytes := addr.As16() 596 return IPv6MulticastScope(addrBytes[ipv6MulticastAddressScopeByteIdx] & ipv6MulticastAddressScopeMask) 597 }