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