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