Source file src/net/netip/netip.go

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package netip defines an IP address type that's a small value type.
     6  // Building on that [Addr] type, the package also defines [AddrPort] (an
     7  // IP address and a port) and [Prefix] (an IP address and a bit length
     8  // prefix).
     9  //
    10  // Compared to the [net.IP] type, [Addr] type takes less memory, is immutable,
    11  // and is comparable (supports == and being a map key).
    12  package netip
    13  
    14  import (
    15  	"cmp"
    16  	"errors"
    17  	"math"
    18  	"strconv"
    19  
    20  	"internal/bytealg"
    21  	"internal/intern"
    22  	"internal/itoa"
    23  )
    24  
    25  // Sizes: (64-bit)
    26  //   net.IP:     24 byte slice header + {4, 16} = 28 to 40 bytes
    27  //   net.IPAddr: 40 byte slice header + {4, 16} = 44 to 56 bytes + zone length
    28  //   netip.Addr: 24 bytes (zone is per-name singleton, shared across all users)
    29  
    30  // Addr represents an IPv4 or IPv6 address (with or without a scoped
    31  // addressing zone), similar to [net.IP] or [net.IPAddr].
    32  //
    33  // Unlike [net.IP] or [net.IPAddr], Addr is a comparable value
    34  // type (it supports == and can be a map key) and is immutable.
    35  //
    36  // The zero Addr is not a valid IP address.
    37  // Addr{} is distinct from both 0.0.0.0 and ::.
    38  type Addr struct {
    39  	// addr is the hi and lo bits of an IPv6 address. If z==z4,
    40  	// hi and lo contain the IPv4-mapped IPv6 address.
    41  	//
    42  	// hi and lo are constructed by interpreting a 16-byte IPv6
    43  	// address as a big-endian 128-bit number. The most significant
    44  	// bits of that number go into hi, the rest into lo.
    45  	//
    46  	// For example, 0011:2233:4455:6677:8899:aabb:ccdd:eeff is stored as:
    47  	//  addr.hi = 0x0011223344556677
    48  	//  addr.lo = 0x8899aabbccddeeff
    49  	//
    50  	// We store IPs like this, rather than as [16]byte, because it
    51  	// turns most operations on IPs into arithmetic and bit-twiddling
    52  	// operations on 64-bit registers, which is much faster than
    53  	// bytewise processing.
    54  	addr uint128
    55  
    56  	// z is a combination of the address family and the IPv6 zone.
    57  	//
    58  	// nil means invalid IP address (for a zero Addr).
    59  	// z4 means an IPv4 address.
    60  	// z6noz means an IPv6 address without a zone.
    61  	//
    62  	// Otherwise it's the interned zone name string.
    63  	z *intern.Value
    64  }
    65  
    66  // z0, z4, and z6noz are sentinel Addr.z values.
    67  // See the Addr type's field docs.
    68  var (
    69  	z0    = (*intern.Value)(nil)
    70  	z4    = new(intern.Value)
    71  	z6noz = new(intern.Value)
    72  )
    73  
    74  // IPv6LinkLocalAllNodes returns the IPv6 link-local all nodes multicast
    75  // address ff02::1.
    76  func IPv6LinkLocalAllNodes() Addr { return AddrFrom16([16]byte{0: 0xff, 1: 0x02, 15: 0x01}) }
    77  
    78  // IPv6LinkLocalAllRouters returns the IPv6 link-local all routers multicast
    79  // address ff02::2.
    80  func IPv6LinkLocalAllRouters() Addr { return AddrFrom16([16]byte{0: 0xff, 1: 0x02, 15: 0x02}) }
    81  
    82  // IPv6Loopback returns the IPv6 loopback address ::1.
    83  func IPv6Loopback() Addr { return AddrFrom16([16]byte{15: 0x01}) }
    84  
    85  // IPv6Unspecified returns the IPv6 unspecified address "::".
    86  func IPv6Unspecified() Addr { return Addr{z: z6noz} }
    87  
    88  // IPv4Unspecified returns the IPv4 unspecified address "0.0.0.0".
    89  func IPv4Unspecified() Addr { return AddrFrom4([4]byte{}) }
    90  
    91  // AddrFrom4 returns the address of the IPv4 address given by the bytes in addr.
    92  func AddrFrom4(addr [4]byte) Addr {
    93  	return Addr{
    94  		addr: uint128{0, 0xffff00000000 | uint64(addr[0])<<24 | uint64(addr[1])<<16 | uint64(addr[2])<<8 | uint64(addr[3])},
    95  		z:    z4,
    96  	}
    97  }
    98  
    99  // AddrFrom16 returns the IPv6 address given by the bytes in addr.
   100  // An IPv4-mapped IPv6 address is left as an IPv6 address.
   101  // (Use Unmap to convert them if needed.)
   102  func AddrFrom16(addr [16]byte) Addr {
   103  	return Addr{
   104  		addr: uint128{
   105  			beUint64(addr[:8]),
   106  			beUint64(addr[8:]),
   107  		},
   108  		z: z6noz,
   109  	}
   110  }
   111  
   112  // ParseAddr parses s as an IP address, returning the result. The string
   113  // s can be in dotted decimal ("192.0.2.1"), IPv6 ("2001:db8::68"),
   114  // or IPv6 with a scoped addressing zone ("fe80::1cc0:3e8c:119f:c2e1%ens18").
   115  func ParseAddr(s string) (Addr, error) {
   116  	for i := 0; i < len(s); i++ {
   117  		switch s[i] {
   118  		case '.':
   119  			return parseIPv4(s)
   120  		case ':':
   121  			return parseIPv6(s)
   122  		case '%':
   123  			// Assume that this was trying to be an IPv6 address with
   124  			// a zone specifier, but the address is missing.
   125  			return Addr{}, parseAddrError{in: s, msg: "missing IPv6 address"}
   126  		}
   127  	}
   128  	return Addr{}, parseAddrError{in: s, msg: "unable to parse IP"}
   129  }
   130  
   131  // MustParseAddr calls [ParseAddr](s) and panics on error.
   132  // It is intended for use in tests with hard-coded strings.
   133  func MustParseAddr(s string) Addr {
   134  	ip, err := ParseAddr(s)
   135  	if err != nil {
   136  		panic(err)
   137  	}
   138  	return ip
   139  }
   140  
   141  type parseAddrError struct {
   142  	in  string // the string given to ParseAddr
   143  	msg string // an explanation of the parse failure
   144  	at  string // optionally, the unparsed portion of in at which the error occurred.
   145  }
   146  
   147  func (err parseAddrError) Error() string {
   148  	q := strconv.Quote
   149  	if err.at != "" {
   150  		return "ParseAddr(" + q(err.in) + "): " + err.msg + " (at " + q(err.at) + ")"
   151  	}
   152  	return "ParseAddr(" + q(err.in) + "): " + err.msg
   153  }
   154  
   155  // parseIPv4 parses s as an IPv4 address (in form "192.168.0.1").
   156  func parseIPv4(s string) (ip Addr, err error) {
   157  	var fields [4]uint8
   158  	var val, pos int
   159  	var digLen int // number of digits in current octet
   160  	for i := 0; i < len(s); i++ {
   161  		if s[i] >= '0' && s[i] <= '9' {
   162  			if digLen == 1 && val == 0 {
   163  				return Addr{}, parseAddrError{in: s, msg: "IPv4 field has octet with leading zero"}
   164  			}
   165  			val = val*10 + int(s[i]) - '0'
   166  			digLen++
   167  			if val > 255 {
   168  				return Addr{}, parseAddrError{in: s, msg: "IPv4 field has value >255"}
   169  			}
   170  		} else if s[i] == '.' {
   171  			// .1.2.3
   172  			// 1.2.3.
   173  			// 1..2.3
   174  			if i == 0 || i == len(s)-1 || s[i-1] == '.' {
   175  				return Addr{}, parseAddrError{in: s, msg: "IPv4 field must have at least one digit", at: s[i:]}
   176  			}
   177  			// 1.2.3.4.5
   178  			if pos == 3 {
   179  				return Addr{}, parseAddrError{in: s, msg: "IPv4 address too long"}
   180  			}
   181  			fields[pos] = uint8(val)
   182  			pos++
   183  			val = 0
   184  			digLen = 0
   185  		} else {
   186  			return Addr{}, parseAddrError{in: s, msg: "unexpected character", at: s[i:]}
   187  		}
   188  	}
   189  	if pos < 3 {
   190  		return Addr{}, parseAddrError{in: s, msg: "IPv4 address too short"}
   191  	}
   192  	fields[3] = uint8(val)
   193  	return AddrFrom4(fields), nil
   194  }
   195  
   196  // parseIPv6 parses s as an IPv6 address (in form "2001:db8::68").
   197  func parseIPv6(in string) (Addr, error) {
   198  	s := in
   199  
   200  	// Split off the zone right from the start. Yes it's a second scan
   201  	// of the string, but trying to handle it inline makes a bunch of
   202  	// other inner loop conditionals more expensive, and it ends up
   203  	// being slower.
   204  	zone := ""
   205  	i := bytealg.IndexByteString(s, '%')
   206  	if i != -1 {
   207  		s, zone = s[:i], s[i+1:]
   208  		if zone == "" {
   209  			// Not allowed to have an empty zone if explicitly specified.
   210  			return Addr{}, parseAddrError{in: in, msg: "zone must be a non-empty string"}
   211  		}
   212  	}
   213  
   214  	var ip [16]byte
   215  	ellipsis := -1 // position of ellipsis in ip
   216  
   217  	// Might have leading ellipsis
   218  	if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
   219  		ellipsis = 0
   220  		s = s[2:]
   221  		// Might be only ellipsis
   222  		if len(s) == 0 {
   223  			return IPv6Unspecified().WithZone(zone), nil
   224  		}
   225  	}
   226  
   227  	// Loop, parsing hex numbers followed by colon.
   228  	i = 0
   229  	for i < 16 {
   230  		// Hex number. Similar to parseIPv4, inlining the hex number
   231  		// parsing yields a significant performance increase.
   232  		off := 0
   233  		acc := uint32(0)
   234  		for ; off < len(s); off++ {
   235  			c := s[off]
   236  			if c >= '0' && c <= '9' {
   237  				acc = (acc << 4) + uint32(c-'0')
   238  			} else if c >= 'a' && c <= 'f' {
   239  				acc = (acc << 4) + uint32(c-'a'+10)
   240  			} else if c >= 'A' && c <= 'F' {
   241  				acc = (acc << 4) + uint32(c-'A'+10)
   242  			} else {
   243  				break
   244  			}
   245  			if acc > math.MaxUint16 {
   246  				// Overflow, fail.
   247  				return Addr{}, parseAddrError{in: in, msg: "IPv6 field has value >=2^16", at: s}
   248  			}
   249  		}
   250  		if off == 0 {
   251  			// No digits found, fail.
   252  			return Addr{}, parseAddrError{in: in, msg: "each colon-separated field must have at least one digit", at: s}
   253  		}
   254  
   255  		// If followed by dot, might be in trailing IPv4.
   256  		if off < len(s) && s[off] == '.' {
   257  			if ellipsis < 0 && i != 12 {
   258  				// Not the right place.
   259  				return Addr{}, parseAddrError{in: in, msg: "embedded IPv4 address must replace the final 2 fields of the address", at: s}
   260  			}
   261  			if i+4 > 16 {
   262  				// Not enough room.
   263  				return Addr{}, parseAddrError{in: in, msg: "too many hex fields to fit an embedded IPv4 at the end of the address", at: s}
   264  			}
   265  			// TODO: could make this a bit faster by having a helper
   266  			// that parses to a [4]byte, and have both parseIPv4 and
   267  			// parseIPv6 use it.
   268  			ip4, err := parseIPv4(s)
   269  			if err != nil {
   270  				return Addr{}, parseAddrError{in: in, msg: err.Error(), at: s}
   271  			}
   272  			ip[i] = ip4.v4(0)
   273  			ip[i+1] = ip4.v4(1)
   274  			ip[i+2] = ip4.v4(2)
   275  			ip[i+3] = ip4.v4(3)
   276  			s = ""
   277  			i += 4
   278  			break
   279  		}
   280  
   281  		// Save this 16-bit chunk.
   282  		ip[i] = byte(acc >> 8)
   283  		ip[i+1] = byte(acc)
   284  		i += 2
   285  
   286  		// Stop at end of string.
   287  		s = s[off:]
   288  		if len(s) == 0 {
   289  			break
   290  		}
   291  
   292  		// Otherwise must be followed by colon and more.
   293  		if s[0] != ':' {
   294  			return Addr{}, parseAddrError{in: in, msg: "unexpected character, want colon", at: s}
   295  		} else if len(s) == 1 {
   296  			return Addr{}, parseAddrError{in: in, msg: "colon must be followed by more characters", at: s}
   297  		}
   298  		s = s[1:]
   299  
   300  		// Look for ellipsis.
   301  		if s[0] == ':' {
   302  			if ellipsis >= 0 { // already have one
   303  				return Addr{}, parseAddrError{in: in, msg: "multiple :: in address", at: s}
   304  			}
   305  			ellipsis = i
   306  			s = s[1:]
   307  			if len(s) == 0 { // can be at end
   308  				break
   309  			}
   310  		}
   311  	}
   312  
   313  	// Must have used entire string.
   314  	if len(s) != 0 {
   315  		return Addr{}, parseAddrError{in: in, msg: "trailing garbage after address", at: s}
   316  	}
   317  
   318  	// If didn't parse enough, expand ellipsis.
   319  	if i < 16 {
   320  		if ellipsis < 0 {
   321  			return Addr{}, parseAddrError{in: in, msg: "address string too short"}
   322  		}
   323  		n := 16 - i
   324  		for j := i - 1; j >= ellipsis; j-- {
   325  			ip[j+n] = ip[j]
   326  		}
   327  		for j := ellipsis + n - 1; j >= ellipsis; j-- {
   328  			ip[j] = 0
   329  		}
   330  	} else if ellipsis >= 0 {
   331  		// Ellipsis must represent at least one 0 group.
   332  		return Addr{}, parseAddrError{in: in, msg: "the :: must expand to at least one field of zeros"}
   333  	}
   334  	return AddrFrom16(ip).WithZone(zone), nil
   335  }
   336  
   337  // AddrFromSlice parses the 4- or 16-byte byte slice as an IPv4 or IPv6 address.
   338  // Note that a [net.IP] can be passed directly as the []byte argument.
   339  // If slice's length is not 4 or 16, AddrFromSlice returns [Addr]{}, false.
   340  func AddrFromSlice(slice []byte) (ip Addr, ok bool) {
   341  	switch len(slice) {
   342  	case 4:
   343  		return AddrFrom4([4]byte(slice)), true
   344  	case 16:
   345  		return AddrFrom16([16]byte(slice)), true
   346  	}
   347  	return Addr{}, false
   348  }
   349  
   350  // v4 returns the i'th byte of ip. If ip is not an IPv4, v4 returns
   351  // unspecified garbage.
   352  func (ip Addr) v4(i uint8) uint8 {
   353  	return uint8(ip.addr.lo >> ((3 - i) * 8))
   354  }
   355  
   356  // v6 returns the i'th byte of ip. If ip is an IPv4 address, this
   357  // accesses the IPv4-mapped IPv6 address form of the IP.
   358  func (ip Addr) v6(i uint8) uint8 {
   359  	return uint8(*(ip.addr.halves()[(i/8)%2]) >> ((7 - i%8) * 8))
   360  }
   361  
   362  // v6u16 returns the i'th 16-bit word of ip. If ip is an IPv4 address,
   363  // this accesses the IPv4-mapped IPv6 address form of the IP.
   364  func (ip Addr) v6u16(i uint8) uint16 {
   365  	return uint16(*(ip.addr.halves()[(i/4)%2]) >> ((3 - i%4) * 16))
   366  }
   367  
   368  // isZero reports whether ip is the zero value of the IP type.
   369  // The zero value is not a valid IP address of any type.
   370  //
   371  // Note that "0.0.0.0" and "::" are not the zero value. Use IsUnspecified to
   372  // check for these values instead.
   373  func (ip Addr) isZero() bool {
   374  	// Faster than comparing ip == Addr{}, but effectively equivalent,
   375  	// as there's no way to make an IP with a nil z from this package.
   376  	return ip.z == z0
   377  }
   378  
   379  // IsValid reports whether the [Addr] is an initialized address (not the zero Addr).
   380  //
   381  // Note that "0.0.0.0" and "::" are both valid values.
   382  func (ip Addr) IsValid() bool { return ip.z != z0 }
   383  
   384  // BitLen returns the number of bits in the IP address:
   385  // 128 for IPv6, 32 for IPv4, and 0 for the zero [Addr].
   386  //
   387  // Note that IPv4-mapped IPv6 addresses are considered IPv6 addresses
   388  // and therefore have bit length 128.
   389  func (ip Addr) BitLen() int {
   390  	switch ip.z {
   391  	case z0:
   392  		return 0
   393  	case z4:
   394  		return 32
   395  	}
   396  	return 128
   397  }
   398  
   399  // Zone returns ip's IPv6 scoped addressing zone, if any.
   400  func (ip Addr) Zone() string {
   401  	if ip.z == nil {
   402  		return ""
   403  	}
   404  	zone, _ := ip.z.Get().(string)
   405  	return zone
   406  }
   407  
   408  // Compare returns an integer comparing two IPs.
   409  // The result will be 0 if ip == ip2, -1 if ip < ip2, and +1 if ip > ip2.
   410  // The definition of "less than" is the same as the [Addr.Less] method.
   411  func (ip Addr) Compare(ip2 Addr) int {
   412  	f1, f2 := ip.BitLen(), ip2.BitLen()
   413  	if f1 < f2 {
   414  		return -1
   415  	}
   416  	if f1 > f2 {
   417  		return 1
   418  	}
   419  	hi1, hi2 := ip.addr.hi, ip2.addr.hi
   420  	if hi1 < hi2 {
   421  		return -1
   422  	}
   423  	if hi1 > hi2 {
   424  		return 1
   425  	}
   426  	lo1, lo2 := ip.addr.lo, ip2.addr.lo
   427  	if lo1 < lo2 {
   428  		return -1
   429  	}
   430  	if lo1 > lo2 {
   431  		return 1
   432  	}
   433  	if ip.Is6() {
   434  		za, zb := ip.Zone(), ip2.Zone()
   435  		if za < zb {
   436  			return -1
   437  		}
   438  		if za > zb {
   439  			return 1
   440  		}
   441  	}
   442  	return 0
   443  }
   444  
   445  // Less reports whether ip sorts before ip2.
   446  // IP addresses sort first by length, then their address.
   447  // IPv6 addresses with zones sort just after the same address without a zone.
   448  func (ip Addr) Less(ip2 Addr) bool { return ip.Compare(ip2) == -1 }
   449  
   450  // Is4 reports whether ip is an IPv4 address.
   451  //
   452  // It returns false for IPv4-mapped IPv6 addresses. See [Addr.Unmap].
   453  func (ip Addr) Is4() bool {
   454  	return ip.z == z4
   455  }
   456  
   457  // Is4In6 reports whether ip is an IPv4-mapped IPv6 address.
   458  func (ip Addr) Is4In6() bool {
   459  	return ip.Is6() && ip.addr.hi == 0 && ip.addr.lo>>32 == 0xffff
   460  }
   461  
   462  // Is6 reports whether ip is an IPv6 address, including IPv4-mapped
   463  // IPv6 addresses.
   464  func (ip Addr) Is6() bool {
   465  	return ip.z != z0 && ip.z != z4
   466  }
   467  
   468  // Unmap returns ip with any IPv4-mapped IPv6 address prefix removed.
   469  //
   470  // That is, if ip is an IPv6 address wrapping an IPv4 address, it
   471  // returns the wrapped IPv4 address. Otherwise it returns ip unmodified.
   472  func (ip Addr) Unmap() Addr {
   473  	if ip.Is4In6() {
   474  		ip.z = z4
   475  	}
   476  	return ip
   477  }
   478  
   479  // WithZone returns an IP that's the same as ip but with the provided
   480  // zone. If zone is empty, the zone is removed. If ip is an IPv4
   481  // address, WithZone is a no-op and returns ip unchanged.
   482  func (ip Addr) WithZone(zone string) Addr {
   483  	if !ip.Is6() {
   484  		return ip
   485  	}
   486  	if zone == "" {
   487  		ip.z = z6noz
   488  		return ip
   489  	}
   490  	ip.z = intern.GetByString(zone)
   491  	return ip
   492  }
   493  
   494  // withoutZone unconditionally strips the zone from ip.
   495  // It's similar to WithZone, but small enough to be inlinable.
   496  func (ip Addr) withoutZone() Addr {
   497  	if !ip.Is6() {
   498  		return ip
   499  	}
   500  	ip.z = z6noz
   501  	return ip
   502  }
   503  
   504  // hasZone reports whether ip has an IPv6 zone.
   505  func (ip Addr) hasZone() bool {
   506  	return ip.z != z0 && ip.z != z4 && ip.z != z6noz
   507  }
   508  
   509  // IsLinkLocalUnicast reports whether ip is a link-local unicast address.
   510  func (ip Addr) IsLinkLocalUnicast() bool {
   511  	if ip.Is4In6() {
   512  		ip = ip.Unmap()
   513  	}
   514  
   515  	// Dynamic Configuration of IPv4 Link-Local Addresses
   516  	// https://datatracker.ietf.org/doc/html/rfc3927#section-2.1
   517  	if ip.Is4() {
   518  		return ip.v4(0) == 169 && ip.v4(1) == 254
   519  	}
   520  	// IP Version 6 Addressing Architecture (2.4 Address Type Identification)
   521  	// https://datatracker.ietf.org/doc/html/rfc4291#section-2.4
   522  	if ip.Is6() {
   523  		return ip.v6u16(0)&0xffc0 == 0xfe80
   524  	}
   525  	return false // zero value
   526  }
   527  
   528  // IsLoopback reports whether ip is a loopback address.
   529  func (ip Addr) IsLoopback() bool {
   530  	if ip.Is4In6() {
   531  		ip = ip.Unmap()
   532  	}
   533  
   534  	// Requirements for Internet Hosts -- Communication Layers (3.2.1.3 Addressing)
   535  	// https://datatracker.ietf.org/doc/html/rfc1122#section-3.2.1.3
   536  	if ip.Is4() {
   537  		return ip.v4(0) == 127
   538  	}
   539  	// IP Version 6 Addressing Architecture (2.4 Address Type Identification)
   540  	// https://datatracker.ietf.org/doc/html/rfc4291#section-2.4
   541  	if ip.Is6() {
   542  		return ip.addr.hi == 0 && ip.addr.lo == 1
   543  	}
   544  	return false // zero value
   545  }
   546  
   547  // IsMulticast reports whether ip is a multicast address.
   548  func (ip Addr) IsMulticast() bool {
   549  	if ip.Is4In6() {
   550  		ip = ip.Unmap()
   551  	}
   552  
   553  	// Host Extensions for IP Multicasting (4. HOST GROUP ADDRESSES)
   554  	// https://datatracker.ietf.org/doc/html/rfc1112#section-4
   555  	if ip.Is4() {
   556  		return ip.v4(0)&0xf0 == 0xe0
   557  	}
   558  	// IP Version 6 Addressing Architecture (2.4 Address Type Identification)
   559  	// https://datatracker.ietf.org/doc/html/rfc4291#section-2.4
   560  	if ip.Is6() {
   561  		return ip.addr.hi>>(64-8) == 0xff // ip.v6(0) == 0xff
   562  	}
   563  	return false // zero value
   564  }
   565  
   566  // IsInterfaceLocalMulticast reports whether ip is an IPv6 interface-local
   567  // multicast address.
   568  func (ip Addr) IsInterfaceLocalMulticast() bool {
   569  	// IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses)
   570  	// https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1
   571  	if ip.Is6() && !ip.Is4In6() {
   572  		return ip.v6u16(0)&0xff0f == 0xff01
   573  	}
   574  	return false // zero value
   575  }
   576  
   577  // IsLinkLocalMulticast reports whether ip is a link-local multicast address.
   578  func (ip Addr) IsLinkLocalMulticast() bool {
   579  	if ip.Is4In6() {
   580  		ip = ip.Unmap()
   581  	}
   582  
   583  	// IPv4 Multicast Guidelines (4. Local Network Control Block (224.0.0/24))
   584  	// https://datatracker.ietf.org/doc/html/rfc5771#section-4
   585  	if ip.Is4() {
   586  		return ip.v4(0) == 224 && ip.v4(1) == 0 && ip.v4(2) == 0
   587  	}
   588  	// IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses)
   589  	// https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1
   590  	if ip.Is6() {
   591  		return ip.v6u16(0)&0xff0f == 0xff02
   592  	}
   593  	return false // zero value
   594  }
   595  
   596  // IsGlobalUnicast reports whether ip is a global unicast address.
   597  //
   598  // It returns true for IPv6 addresses which fall outside of the current
   599  // IANA-allocated 2000::/3 global unicast space, with the exception of the
   600  // link-local address space. It also returns true even if ip is in the IPv4
   601  // private address space or IPv6 unique local address space.
   602  // It returns false for the zero [Addr].
   603  //
   604  // For reference, see RFC 1122, RFC 4291, and RFC 4632.
   605  func (ip Addr) IsGlobalUnicast() bool {
   606  	if ip.z == z0 {
   607  		// Invalid or zero-value.
   608  		return false
   609  	}
   610  
   611  	if ip.Is4In6() {
   612  		ip = ip.Unmap()
   613  	}
   614  
   615  	// Match package net's IsGlobalUnicast logic. Notably private IPv4 addresses
   616  	// and ULA IPv6 addresses are still considered "global unicast".
   617  	if ip.Is4() && (ip == IPv4Unspecified() || ip == AddrFrom4([4]byte{255, 255, 255, 255})) {
   618  		return false
   619  	}
   620  
   621  	return ip != IPv6Unspecified() &&
   622  		!ip.IsLoopback() &&
   623  		!ip.IsMulticast() &&
   624  		!ip.IsLinkLocalUnicast()
   625  }
   626  
   627  // IsPrivate reports whether ip is a private address, according to RFC 1918
   628  // (IPv4 addresses) and RFC 4193 (IPv6 addresses). That is, it reports whether
   629  // ip is in 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or fc00::/7. This is the
   630  // same as [net.IP.IsPrivate].
   631  func (ip Addr) IsPrivate() bool {
   632  	if ip.Is4In6() {
   633  		ip = ip.Unmap()
   634  	}
   635  
   636  	// Match the stdlib's IsPrivate logic.
   637  	if ip.Is4() {
   638  		// RFC 1918 allocates 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 as
   639  		// private IPv4 address subnets.
   640  		return ip.v4(0) == 10 ||
   641  			(ip.v4(0) == 172 && ip.v4(1)&0xf0 == 16) ||
   642  			(ip.v4(0) == 192 && ip.v4(1) == 168)
   643  	}
   644  
   645  	if ip.Is6() {
   646  		// RFC 4193 allocates fc00::/7 as the unique local unicast IPv6 address
   647  		// subnet.
   648  		return ip.v6(0)&0xfe == 0xfc
   649  	}
   650  
   651  	return false // zero value
   652  }
   653  
   654  // IsUnspecified reports whether ip is an unspecified address, either the IPv4
   655  // address "0.0.0.0" or the IPv6 address "::".
   656  //
   657  // Note that the zero [Addr] is not an unspecified address.
   658  func (ip Addr) IsUnspecified() bool {
   659  	return ip == IPv4Unspecified() || ip == IPv6Unspecified()
   660  }
   661  
   662  // Prefix keeps only the top b bits of IP, producing a Prefix
   663  // of the specified length.
   664  // If ip is a zero [Addr], Prefix always returns a zero Prefix and a nil error.
   665  // Otherwise, if bits is less than zero or greater than ip.BitLen(),
   666  // Prefix returns an error.
   667  func (ip Addr) Prefix(b int) (Prefix, error) {
   668  	if b < 0 {
   669  		return Prefix{}, errors.New("negative Prefix bits")
   670  	}
   671  	effectiveBits := b
   672  	switch ip.z {
   673  	case z0:
   674  		return Prefix{}, nil
   675  	case z4:
   676  		if b > 32 {
   677  			return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv4")
   678  		}
   679  		effectiveBits += 96
   680  	default:
   681  		if b > 128 {
   682  			return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv6")
   683  		}
   684  	}
   685  	ip.addr = ip.addr.and(mask6(effectiveBits))
   686  	return PrefixFrom(ip, b), nil
   687  }
   688  
   689  // As16 returns the IP address in its 16-byte representation.
   690  // IPv4 addresses are returned as IPv4-mapped IPv6 addresses.
   691  // IPv6 addresses with zones are returned without their zone (use the
   692  // [Addr.Zone] method to get it).
   693  // The ip zero value returns all zeroes.
   694  func (ip Addr) As16() (a16 [16]byte) {
   695  	bePutUint64(a16[:8], ip.addr.hi)
   696  	bePutUint64(a16[8:], ip.addr.lo)
   697  	return a16
   698  }
   699  
   700  // As4 returns an IPv4 or IPv4-in-IPv6 address in its 4-byte representation.
   701  // If ip is the zero [Addr] or an IPv6 address, As4 panics.
   702  // Note that 0.0.0.0 is not the zero Addr.
   703  func (ip Addr) As4() (a4 [4]byte) {
   704  	if ip.z == z4 || ip.Is4In6() {
   705  		bePutUint32(a4[:], uint32(ip.addr.lo))
   706  		return a4
   707  	}
   708  	if ip.z == z0 {
   709  		panic("As4 called on IP zero value")
   710  	}
   711  	panic("As4 called on IPv6 address")
   712  }
   713  
   714  // AsSlice returns an IPv4 or IPv6 address in its respective 4-byte or 16-byte representation.
   715  func (ip Addr) AsSlice() []byte {
   716  	switch ip.z {
   717  	case z0:
   718  		return nil
   719  	case z4:
   720  		var ret [4]byte
   721  		bePutUint32(ret[:], uint32(ip.addr.lo))
   722  		return ret[:]
   723  	default:
   724  		var ret [16]byte
   725  		bePutUint64(ret[:8], ip.addr.hi)
   726  		bePutUint64(ret[8:], ip.addr.lo)
   727  		return ret[:]
   728  	}
   729  }
   730  
   731  // Next returns the address following ip.
   732  // If there is none, it returns the zero [Addr].
   733  func (ip Addr) Next() Addr {
   734  	ip.addr = ip.addr.addOne()
   735  	if ip.Is4() {
   736  		if uint32(ip.addr.lo) == 0 {
   737  			// Overflowed.
   738  			return Addr{}
   739  		}
   740  	} else {
   741  		if ip.addr.isZero() {
   742  			// Overflowed
   743  			return Addr{}
   744  		}
   745  	}
   746  	return ip
   747  }
   748  
   749  // Prev returns the IP before ip.
   750  // If there is none, it returns the IP zero value.
   751  func (ip Addr) Prev() Addr {
   752  	if ip.Is4() {
   753  		if uint32(ip.addr.lo) == 0 {
   754  			return Addr{}
   755  		}
   756  	} else if ip.addr.isZero() {
   757  		return Addr{}
   758  	}
   759  	ip.addr = ip.addr.subOne()
   760  	return ip
   761  }
   762  
   763  // String returns the string form of the IP address ip.
   764  // It returns one of 5 forms:
   765  //
   766  //   - "invalid IP", if ip is the zero [Addr]
   767  //   - IPv4 dotted decimal ("192.0.2.1")
   768  //   - IPv6 ("2001:db8::1")
   769  //   - "::ffff:1.2.3.4" (if [Addr.Is4In6])
   770  //   - IPv6 with zone ("fe80:db8::1%eth0")
   771  //
   772  // Note that unlike package net's IP.String method,
   773  // IPv4-mapped IPv6 addresses format with a "::ffff:"
   774  // prefix before the dotted quad.
   775  func (ip Addr) String() string {
   776  	switch ip.z {
   777  	case z0:
   778  		return "invalid IP"
   779  	case z4:
   780  		return ip.string4()
   781  	default:
   782  		if ip.Is4In6() {
   783  			if z := ip.Zone(); z != "" {
   784  				return "::ffff:" + ip.Unmap().string4() + "%" + z
   785  			} else {
   786  				return "::ffff:" + ip.Unmap().string4()
   787  			}
   788  		}
   789  		return ip.string6()
   790  	}
   791  }
   792  
   793  // AppendTo appends a text encoding of ip,
   794  // as generated by [Addr.MarshalText],
   795  // to b and returns the extended buffer.
   796  func (ip Addr) AppendTo(b []byte) []byte {
   797  	switch ip.z {
   798  	case z0:
   799  		return b
   800  	case z4:
   801  		return ip.appendTo4(b)
   802  	default:
   803  		if ip.Is4In6() {
   804  			b = append(b, "::ffff:"...)
   805  			b = ip.Unmap().appendTo4(b)
   806  			if z := ip.Zone(); z != "" {
   807  				b = append(b, '%')
   808  				b = append(b, z...)
   809  			}
   810  			return b
   811  		}
   812  		return ip.appendTo6(b)
   813  	}
   814  }
   815  
   816  // digits is a string of the hex digits from 0 to f. It's used in
   817  // appendDecimal and appendHex to format IP addresses.
   818  const digits = "0123456789abcdef"
   819  
   820  // appendDecimal appends the decimal string representation of x to b.
   821  func appendDecimal(b []byte, x uint8) []byte {
   822  	// Using this function rather than strconv.AppendUint makes IPv4
   823  	// string building 2x faster.
   824  
   825  	if x >= 100 {
   826  		b = append(b, digits[x/100])
   827  	}
   828  	if x >= 10 {
   829  		b = append(b, digits[x/10%10])
   830  	}
   831  	return append(b, digits[x%10])
   832  }
   833  
   834  // appendHex appends the hex string representation of x to b.
   835  func appendHex(b []byte, x uint16) []byte {
   836  	// Using this function rather than strconv.AppendUint makes IPv6
   837  	// string building 2x faster.
   838  
   839  	if x >= 0x1000 {
   840  		b = append(b, digits[x>>12])
   841  	}
   842  	if x >= 0x100 {
   843  		b = append(b, digits[x>>8&0xf])
   844  	}
   845  	if x >= 0x10 {
   846  		b = append(b, digits[x>>4&0xf])
   847  	}
   848  	return append(b, digits[x&0xf])
   849  }
   850  
   851  // appendHexPad appends the fully padded hex string representation of x to b.
   852  func appendHexPad(b []byte, x uint16) []byte {
   853  	return append(b, digits[x>>12], digits[x>>8&0xf], digits[x>>4&0xf], digits[x&0xf])
   854  }
   855  
   856  func (ip Addr) string4() string {
   857  	const max = len("255.255.255.255")
   858  	ret := make([]byte, 0, max)
   859  	ret = ip.appendTo4(ret)
   860  	return string(ret)
   861  }
   862  
   863  func (ip Addr) appendTo4(ret []byte) []byte {
   864  	ret = appendDecimal(ret, ip.v4(0))
   865  	ret = append(ret, '.')
   866  	ret = appendDecimal(ret, ip.v4(1))
   867  	ret = append(ret, '.')
   868  	ret = appendDecimal(ret, ip.v4(2))
   869  	ret = append(ret, '.')
   870  	ret = appendDecimal(ret, ip.v4(3))
   871  	return ret
   872  }
   873  
   874  // string6 formats ip in IPv6 textual representation. It follows the
   875  // guidelines in section 4 of RFC 5952
   876  // (https://tools.ietf.org/html/rfc5952#section-4): no unnecessary
   877  // zeros, use :: to elide the longest run of zeros, and don't use ::
   878  // to compact a single zero field.
   879  func (ip Addr) string6() string {
   880  	// Use a zone with a "plausibly long" name, so that most zone-ful
   881  	// IP addresses won't require additional allocation.
   882  	//
   883  	// The compiler does a cool optimization here, where ret ends up
   884  	// stack-allocated and so the only allocation this function does
   885  	// is to construct the returned string. As such, it's okay to be a
   886  	// bit greedy here, size-wise.
   887  	const max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
   888  	ret := make([]byte, 0, max)
   889  	ret = ip.appendTo6(ret)
   890  	return string(ret)
   891  }
   892  
   893  func (ip Addr) appendTo6(ret []byte) []byte {
   894  	zeroStart, zeroEnd := uint8(255), uint8(255)
   895  	for i := uint8(0); i < 8; i++ {
   896  		j := i
   897  		for j < 8 && ip.v6u16(j) == 0 {
   898  			j++
   899  		}
   900  		if l := j - i; l >= 2 && l > zeroEnd-zeroStart {
   901  			zeroStart, zeroEnd = i, j
   902  		}
   903  	}
   904  
   905  	for i := uint8(0); i < 8; i++ {
   906  		if i == zeroStart {
   907  			ret = append(ret, ':', ':')
   908  			i = zeroEnd
   909  			if i >= 8 {
   910  				break
   911  			}
   912  		} else if i > 0 {
   913  			ret = append(ret, ':')
   914  		}
   915  
   916  		ret = appendHex(ret, ip.v6u16(i))
   917  	}
   918  
   919  	if ip.z != z6noz {
   920  		ret = append(ret, '%')
   921  		ret = append(ret, ip.Zone()...)
   922  	}
   923  	return ret
   924  }
   925  
   926  // StringExpanded is like [Addr.String] but IPv6 addresses are expanded with leading
   927  // zeroes and no "::" compression. For example, "2001:db8::1" becomes
   928  // "2001:0db8:0000:0000:0000:0000:0000:0001".
   929  func (ip Addr) StringExpanded() string {
   930  	switch ip.z {
   931  	case z0, z4:
   932  		return ip.String()
   933  	}
   934  
   935  	const size = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
   936  	ret := make([]byte, 0, size)
   937  	for i := uint8(0); i < 8; i++ {
   938  		if i > 0 {
   939  			ret = append(ret, ':')
   940  		}
   941  
   942  		ret = appendHexPad(ret, ip.v6u16(i))
   943  	}
   944  
   945  	if ip.z != z6noz {
   946  		// The addition of a zone will cause a second allocation, but when there
   947  		// is no zone the ret slice will be stack allocated.
   948  		ret = append(ret, '%')
   949  		ret = append(ret, ip.Zone()...)
   950  	}
   951  	return string(ret)
   952  }
   953  
   954  // MarshalText implements the [encoding.TextMarshaler] interface,
   955  // The encoding is the same as returned by [Addr.String], with one exception:
   956  // If ip is the zero [Addr], the encoding is the empty string.
   957  func (ip Addr) MarshalText() ([]byte, error) {
   958  	switch ip.z {
   959  	case z0:
   960  		return []byte(""), nil
   961  	case z4:
   962  		max := len("255.255.255.255")
   963  		b := make([]byte, 0, max)
   964  		return ip.appendTo4(b), nil
   965  	default:
   966  		max := len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
   967  		b := make([]byte, 0, max)
   968  		if ip.Is4In6() {
   969  			b = append(b, "::ffff:"...)
   970  			b = ip.Unmap().appendTo4(b)
   971  			if z := ip.Zone(); z != "" {
   972  				b = append(b, '%')
   973  				b = append(b, z...)
   974  			}
   975  			return b, nil
   976  		}
   977  		return ip.appendTo6(b), nil
   978  	}
   979  
   980  }
   981  
   982  // UnmarshalText implements the encoding.TextUnmarshaler interface.
   983  // The IP address is expected in a form accepted by [ParseAddr].
   984  //
   985  // If text is empty, UnmarshalText sets *ip to the zero [Addr] and
   986  // returns no error.
   987  func (ip *Addr) UnmarshalText(text []byte) error {
   988  	if len(text) == 0 {
   989  		*ip = Addr{}
   990  		return nil
   991  	}
   992  	var err error
   993  	*ip, err = ParseAddr(string(text))
   994  	return err
   995  }
   996  
   997  func (ip Addr) marshalBinaryWithTrailingBytes(trailingBytes int) []byte {
   998  	var b []byte
   999  	switch ip.z {
  1000  	case z0:
  1001  		b = make([]byte, trailingBytes)
  1002  	case z4:
  1003  		b = make([]byte, 4+trailingBytes)
  1004  		bePutUint32(b, uint32(ip.addr.lo))
  1005  	default:
  1006  		z := ip.Zone()
  1007  		b = make([]byte, 16+len(z)+trailingBytes)
  1008  		bePutUint64(b[:8], ip.addr.hi)
  1009  		bePutUint64(b[8:], ip.addr.lo)
  1010  		copy(b[16:], z)
  1011  	}
  1012  	return b
  1013  }
  1014  
  1015  // MarshalBinary implements the [encoding.BinaryMarshaler] interface.
  1016  // It returns a zero-length slice for the zero [Addr],
  1017  // the 4-byte form for an IPv4 address,
  1018  // and the 16-byte form with zone appended for an IPv6 address.
  1019  func (ip Addr) MarshalBinary() ([]byte, error) {
  1020  	return ip.marshalBinaryWithTrailingBytes(0), nil
  1021  }
  1022  
  1023  // UnmarshalBinary implements the [encoding.BinaryUnmarshaler] interface.
  1024  // It expects data in the form generated by MarshalBinary.
  1025  func (ip *Addr) UnmarshalBinary(b []byte) error {
  1026  	n := len(b)
  1027  	switch {
  1028  	case n == 0:
  1029  		*ip = Addr{}
  1030  		return nil
  1031  	case n == 4:
  1032  		*ip = AddrFrom4([4]byte(b))
  1033  		return nil
  1034  	case n == 16:
  1035  		*ip = AddrFrom16([16]byte(b))
  1036  		return nil
  1037  	case n > 16:
  1038  		*ip = AddrFrom16([16]byte(b[:16])).WithZone(string(b[16:]))
  1039  		return nil
  1040  	}
  1041  	return errors.New("unexpected slice size")
  1042  }
  1043  
  1044  // AddrPort is an IP and a port number.
  1045  type AddrPort struct {
  1046  	ip   Addr
  1047  	port uint16
  1048  }
  1049  
  1050  // AddrPortFrom returns an [AddrPort] with the provided IP and port.
  1051  // It does not allocate.
  1052  func AddrPortFrom(ip Addr, port uint16) AddrPort { return AddrPort{ip: ip, port: port} }
  1053  
  1054  // Addr returns p's IP address.
  1055  func (p AddrPort) Addr() Addr { return p.ip }
  1056  
  1057  // Port returns p's port.
  1058  func (p AddrPort) Port() uint16 { return p.port }
  1059  
  1060  // splitAddrPort splits s into an IP address string and a port
  1061  // string. It splits strings shaped like "foo:bar" or "[foo]:bar",
  1062  // without further validating the substrings. v6 indicates whether the
  1063  // ip string should parse as an IPv6 address or an IPv4 address, in
  1064  // order for s to be a valid ip:port string.
  1065  func splitAddrPort(s string) (ip, port string, v6 bool, err error) {
  1066  	i := bytealg.LastIndexByteString(s, ':')
  1067  	if i == -1 {
  1068  		return "", "", false, errors.New("not an ip:port")
  1069  	}
  1070  
  1071  	ip, port = s[:i], s[i+1:]
  1072  	if len(ip) == 0 {
  1073  		return "", "", false, errors.New("no IP")
  1074  	}
  1075  	if len(port) == 0 {
  1076  		return "", "", false, errors.New("no port")
  1077  	}
  1078  	if ip[0] == '[' {
  1079  		if len(ip) < 2 || ip[len(ip)-1] != ']' {
  1080  			return "", "", false, errors.New("missing ]")
  1081  		}
  1082  		ip = ip[1 : len(ip)-1]
  1083  		v6 = true
  1084  	}
  1085  
  1086  	return ip, port, v6, nil
  1087  }
  1088  
  1089  // ParseAddrPort parses s as an [AddrPort].
  1090  //
  1091  // It doesn't do any name resolution: both the address and the port
  1092  // must be numeric.
  1093  func ParseAddrPort(s string) (AddrPort, error) {
  1094  	var ipp AddrPort
  1095  	ip, port, v6, err := splitAddrPort(s)
  1096  	if err != nil {
  1097  		return ipp, err
  1098  	}
  1099  	port16, err := strconv.ParseUint(port, 10, 16)
  1100  	if err != nil {
  1101  		return ipp, errors.New("invalid port " + strconv.Quote(port) + " parsing " + strconv.Quote(s))
  1102  	}
  1103  	ipp.port = uint16(port16)
  1104  	ipp.ip, err = ParseAddr(ip)
  1105  	if err != nil {
  1106  		return AddrPort{}, err
  1107  	}
  1108  	if v6 && ipp.ip.Is4() {
  1109  		return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", square brackets can only be used with IPv6 addresses")
  1110  	} else if !v6 && ipp.ip.Is6() {
  1111  		return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", IPv6 addresses must be surrounded by square brackets")
  1112  	}
  1113  	return ipp, nil
  1114  }
  1115  
  1116  // MustParseAddrPort calls [ParseAddrPort](s) and panics on error.
  1117  // It is intended for use in tests with hard-coded strings.
  1118  func MustParseAddrPort(s string) AddrPort {
  1119  	ip, err := ParseAddrPort(s)
  1120  	if err != nil {
  1121  		panic(err)
  1122  	}
  1123  	return ip
  1124  }
  1125  
  1126  // IsValid reports whether p.Addr() is valid.
  1127  // All ports are valid, including zero.
  1128  func (p AddrPort) IsValid() bool { return p.ip.IsValid() }
  1129  
  1130  // Compare returns an integer comparing two AddrPorts.
  1131  // The result will be 0 if p == p2, -1 if p < p2, and +1 if p > p2.
  1132  // AddrPorts sort first by IP address, then port.
  1133  func (p AddrPort) Compare(p2 AddrPort) int {
  1134  	if c := p.Addr().Compare(p2.Addr()); c != 0 {
  1135  		return c
  1136  	}
  1137  	return cmp.Compare(p.Port(), p2.Port())
  1138  }
  1139  
  1140  func (p AddrPort) String() string {
  1141  	switch p.ip.z {
  1142  	case z0:
  1143  		return "invalid AddrPort"
  1144  	case z4:
  1145  		const max = len("255.255.255.255:65535")
  1146  		buf := make([]byte, 0, max)
  1147  		buf = p.ip.appendTo4(buf)
  1148  		buf = append(buf, ':')
  1149  		buf = strconv.AppendUint(buf, uint64(p.port), 10)
  1150  		return string(buf)
  1151  	default:
  1152  		// TODO: this could be more efficient allocation-wise:
  1153  		return "[" + p.ip.String() + "]:" + itoa.Uitoa(uint(p.port))
  1154  	}
  1155  }
  1156  
  1157  // AppendTo appends a text encoding of p,
  1158  // as generated by [AddrPort.MarshalText],
  1159  // to b and returns the extended buffer.
  1160  func (p AddrPort) AppendTo(b []byte) []byte {
  1161  	switch p.ip.z {
  1162  	case z0:
  1163  		return b
  1164  	case z4:
  1165  		b = p.ip.appendTo4(b)
  1166  	default:
  1167  		if p.ip.Is4In6() {
  1168  			b = append(b, "[::ffff:"...)
  1169  			b = p.ip.Unmap().appendTo4(b)
  1170  			if z := p.ip.Zone(); z != "" {
  1171  				b = append(b, '%')
  1172  				b = append(b, z...)
  1173  			}
  1174  		} else {
  1175  			b = append(b, '[')
  1176  			b = p.ip.appendTo6(b)
  1177  		}
  1178  		b = append(b, ']')
  1179  	}
  1180  	b = append(b, ':')
  1181  	b = strconv.AppendUint(b, uint64(p.port), 10)
  1182  	return b
  1183  }
  1184  
  1185  // MarshalText implements the [encoding.TextMarshaler] interface. The
  1186  // encoding is the same as returned by [AddrPort.String], with one exception: if
  1187  // p.Addr() is the zero [Addr], the encoding is the empty string.
  1188  func (p AddrPort) MarshalText() ([]byte, error) {
  1189  	var max int
  1190  	switch p.ip.z {
  1191  	case z0:
  1192  	case z4:
  1193  		max = len("255.255.255.255:65535")
  1194  	default:
  1195  		max = len("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0]:65535")
  1196  	}
  1197  	b := make([]byte, 0, max)
  1198  	b = p.AppendTo(b)
  1199  	return b, nil
  1200  }
  1201  
  1202  // UnmarshalText implements the encoding.TextUnmarshaler
  1203  // interface. The [AddrPort] is expected in a form
  1204  // generated by [AddrPort.MarshalText] or accepted by [ParseAddrPort].
  1205  func (p *AddrPort) UnmarshalText(text []byte) error {
  1206  	if len(text) == 0 {
  1207  		*p = AddrPort{}
  1208  		return nil
  1209  	}
  1210  	var err error
  1211  	*p, err = ParseAddrPort(string(text))
  1212  	return err
  1213  }
  1214  
  1215  // MarshalBinary implements the [encoding.BinaryMarshaler] interface.
  1216  // It returns [Addr.MarshalBinary] with an additional two bytes appended
  1217  // containing the port in little-endian.
  1218  func (p AddrPort) MarshalBinary() ([]byte, error) {
  1219  	b := p.Addr().marshalBinaryWithTrailingBytes(2)
  1220  	lePutUint16(b[len(b)-2:], p.Port())
  1221  	return b, nil
  1222  }
  1223  
  1224  // UnmarshalBinary implements the [encoding.BinaryUnmarshaler] interface.
  1225  // It expects data in the form generated by [AddrPort.MarshalBinary].
  1226  func (p *AddrPort) UnmarshalBinary(b []byte) error {
  1227  	if len(b) < 2 {
  1228  		return errors.New("unexpected slice size")
  1229  	}
  1230  	var addr Addr
  1231  	err := addr.UnmarshalBinary(b[:len(b)-2])
  1232  	if err != nil {
  1233  		return err
  1234  	}
  1235  	*p = AddrPortFrom(addr, leUint16(b[len(b)-2:]))
  1236  	return nil
  1237  }
  1238  
  1239  // Prefix is an IP address prefix (CIDR) representing an IP network.
  1240  //
  1241  // The first [Prefix.Bits]() of [Addr]() are specified. The remaining bits match any address.
  1242  // The range of Bits() is [0,32] for IPv4 or [0,128] for IPv6.
  1243  type Prefix struct {
  1244  	ip Addr
  1245  
  1246  	// bitsPlusOne stores the prefix bit length plus one.
  1247  	// A Prefix is valid if and only if bitsPlusOne is non-zero.
  1248  	bitsPlusOne uint8
  1249  }
  1250  
  1251  // PrefixFrom returns a [Prefix] with the provided IP address and bit
  1252  // prefix length.
  1253  //
  1254  // It does not allocate. Unlike [Addr.Prefix], [PrefixFrom] does not mask
  1255  // off the host bits of ip.
  1256  //
  1257  // If bits is less than zero or greater than ip.BitLen, [Prefix.Bits]
  1258  // will return an invalid value -1.
  1259  func PrefixFrom(ip Addr, bits int) Prefix {
  1260  	var bitsPlusOne uint8
  1261  	if !ip.isZero() && bits >= 0 && bits <= ip.BitLen() {
  1262  		bitsPlusOne = uint8(bits) + 1
  1263  	}
  1264  	return Prefix{
  1265  		ip:          ip.withoutZone(),
  1266  		bitsPlusOne: bitsPlusOne,
  1267  	}
  1268  }
  1269  
  1270  // Addr returns p's IP address.
  1271  func (p Prefix) Addr() Addr { return p.ip }
  1272  
  1273  // Bits returns p's prefix length.
  1274  //
  1275  // It reports -1 if invalid.
  1276  func (p Prefix) Bits() int { return int(p.bitsPlusOne) - 1 }
  1277  
  1278  // IsValid reports whether p.Bits() has a valid range for p.Addr().
  1279  // If p.Addr() is the zero [Addr], IsValid returns false.
  1280  // Note that if p is the zero [Prefix], then p.IsValid() == false.
  1281  func (p Prefix) IsValid() bool { return p.bitsPlusOne > 0 }
  1282  
  1283  func (p Prefix) isZero() bool { return p == Prefix{} }
  1284  
  1285  // IsSingleIP reports whether p contains exactly one IP.
  1286  func (p Prefix) IsSingleIP() bool { return p.IsValid() && p.Bits() == p.ip.BitLen() }
  1287  
  1288  // compare returns an integer comparing two prefixes.
  1289  // The result will be 0 if p == p2, -1 if p < p2, and +1 if p > p2.
  1290  // Prefixes sort first by validity (invalid before valid), then
  1291  // address family (IPv4 before IPv6), then prefix length, then
  1292  // address.
  1293  //
  1294  // Unexported for Go 1.22 because we may want to compare by p.Addr first.
  1295  // See post-acceptance discussion on go.dev/issue/61642.
  1296  func (p Prefix) compare(p2 Prefix) int {
  1297  	if c := cmp.Compare(p.Addr().BitLen(), p2.Addr().BitLen()); c != 0 {
  1298  		return c
  1299  	}
  1300  	if c := cmp.Compare(p.Bits(), p2.Bits()); c != 0 {
  1301  		return c
  1302  	}
  1303  	return p.Addr().Compare(p2.Addr())
  1304  }
  1305  
  1306  // ParsePrefix parses s as an IP address prefix.
  1307  // The string can be in the form "192.168.1.0/24" or "2001:db8::/32",
  1308  // the CIDR notation defined in RFC 4632 and RFC 4291.
  1309  // IPv6 zones are not permitted in prefixes, and an error will be returned if a
  1310  // zone is present.
  1311  //
  1312  // Note that masked address bits are not zeroed. Use Masked for that.
  1313  func ParsePrefix(s string) (Prefix, error) {
  1314  	i := bytealg.LastIndexByteString(s, '/')
  1315  	if i < 0 {
  1316  		return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): no '/'")
  1317  	}
  1318  	ip, err := ParseAddr(s[:i])
  1319  	if err != nil {
  1320  		return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): " + err.Error())
  1321  	}
  1322  	// IPv6 zones are not allowed: https://go.dev/issue/51899
  1323  	if ip.Is6() && ip.z != z6noz {
  1324  		return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): IPv6 zones cannot be present in a prefix")
  1325  	}
  1326  
  1327  	bitsStr := s[i+1:]
  1328  
  1329  	// strconv.Atoi accepts a leading sign and leading zeroes, but we don't want that.
  1330  	if len(bitsStr) > 1 && (bitsStr[0] < '1' || bitsStr[0] > '9') {
  1331  		return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): bad bits after slash: " + strconv.Quote(bitsStr))
  1332  	}
  1333  
  1334  	bits, err := strconv.Atoi(bitsStr)
  1335  	if err != nil {
  1336  		return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): bad bits after slash: " + strconv.Quote(bitsStr))
  1337  	}
  1338  	maxBits := 32
  1339  	if ip.Is6() {
  1340  		maxBits = 128
  1341  	}
  1342  	if bits < 0 || bits > maxBits {
  1343  		return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): prefix length out of range")
  1344  	}
  1345  	return PrefixFrom(ip, bits), nil
  1346  }
  1347  
  1348  // MustParsePrefix calls [ParsePrefix](s) and panics on error.
  1349  // It is intended for use in tests with hard-coded strings.
  1350  func MustParsePrefix(s string) Prefix {
  1351  	ip, err := ParsePrefix(s)
  1352  	if err != nil {
  1353  		panic(err)
  1354  	}
  1355  	return ip
  1356  }
  1357  
  1358  // Masked returns p in its canonical form, with all but the high
  1359  // p.Bits() bits of p.Addr() masked off.
  1360  //
  1361  // If p is zero or otherwise invalid, Masked returns the zero [Prefix].
  1362  func (p Prefix) Masked() Prefix {
  1363  	m, _ := p.ip.Prefix(p.Bits())
  1364  	return m
  1365  }
  1366  
  1367  // Contains reports whether the network p includes ip.
  1368  //
  1369  // An IPv4 address will not match an IPv6 prefix.
  1370  // An IPv4-mapped IPv6 address will not match an IPv4 prefix.
  1371  // A zero-value IP will not match any prefix.
  1372  // If ip has an IPv6 zone, Contains returns false,
  1373  // because Prefixes strip zones.
  1374  func (p Prefix) Contains(ip Addr) bool {
  1375  	if !p.IsValid() || ip.hasZone() {
  1376  		return false
  1377  	}
  1378  	if f1, f2 := p.ip.BitLen(), ip.BitLen(); f1 == 0 || f2 == 0 || f1 != f2 {
  1379  		return false
  1380  	}
  1381  	if ip.Is4() {
  1382  		// xor the IP addresses together; mismatched bits are now ones.
  1383  		// Shift away the number of bits we don't care about.
  1384  		// Shifts in Go are more efficient if the compiler can prove
  1385  		// that the shift amount is smaller than the width of the shifted type (64 here).
  1386  		// We know that p.bits is in the range 0..32 because p is Valid;
  1387  		// the compiler doesn't know that, so mask with 63 to help it.
  1388  		// Now truncate to 32 bits, because this is IPv4.
  1389  		// If all the bits we care about are equal, the result will be zero.
  1390  		return uint32((ip.addr.lo^p.ip.addr.lo)>>((32-p.Bits())&63)) == 0
  1391  	} else {
  1392  		// xor the IP addresses together.
  1393  		// Mask away the bits we don't care about.
  1394  		// If all the bits we care about are equal, the result will be zero.
  1395  		return ip.addr.xor(p.ip.addr).and(mask6(p.Bits())).isZero()
  1396  	}
  1397  }
  1398  
  1399  // Overlaps reports whether p and o contain any IP addresses in common.
  1400  //
  1401  // If p and o are of different address families or either have a zero
  1402  // IP, it reports false. Like the Contains method, a prefix with an
  1403  // IPv4-mapped IPv6 address is still treated as an IPv6 mask.
  1404  func (p Prefix) Overlaps(o Prefix) bool {
  1405  	if !p.IsValid() || !o.IsValid() {
  1406  		return false
  1407  	}
  1408  	if p == o {
  1409  		return true
  1410  	}
  1411  	if p.ip.Is4() != o.ip.Is4() {
  1412  		return false
  1413  	}
  1414  	var minBits int
  1415  	if pb, ob := p.Bits(), o.Bits(); pb < ob {
  1416  		minBits = pb
  1417  	} else {
  1418  		minBits = ob
  1419  	}
  1420  	if minBits == 0 {
  1421  		return true
  1422  	}
  1423  	// One of these Prefix calls might look redundant, but we don't require
  1424  	// that p and o values are normalized (via Prefix.Masked) first,
  1425  	// so the Prefix call on the one that's already minBits serves to zero
  1426  	// out any remaining bits in IP.
  1427  	var err error
  1428  	if p, err = p.ip.Prefix(minBits); err != nil {
  1429  		return false
  1430  	}
  1431  	if o, err = o.ip.Prefix(minBits); err != nil {
  1432  		return false
  1433  	}
  1434  	return p.ip == o.ip
  1435  }
  1436  
  1437  // AppendTo appends a text encoding of p,
  1438  // as generated by [Prefix.MarshalText],
  1439  // to b and returns the extended buffer.
  1440  func (p Prefix) AppendTo(b []byte) []byte {
  1441  	if p.isZero() {
  1442  		return b
  1443  	}
  1444  	if !p.IsValid() {
  1445  		return append(b, "invalid Prefix"...)
  1446  	}
  1447  
  1448  	// p.ip is non-nil, because p is valid.
  1449  	if p.ip.z == z4 {
  1450  		b = p.ip.appendTo4(b)
  1451  	} else {
  1452  		if p.ip.Is4In6() {
  1453  			b = append(b, "::ffff:"...)
  1454  			b = p.ip.Unmap().appendTo4(b)
  1455  		} else {
  1456  			b = p.ip.appendTo6(b)
  1457  		}
  1458  	}
  1459  
  1460  	b = append(b, '/')
  1461  	b = appendDecimal(b, uint8(p.Bits()))
  1462  	return b
  1463  }
  1464  
  1465  // MarshalText implements the [encoding.TextMarshaler] interface,
  1466  // The encoding is the same as returned by [Prefix.String], with one exception:
  1467  // If p is the zero value, the encoding is the empty string.
  1468  func (p Prefix) MarshalText() ([]byte, error) {
  1469  	var max int
  1470  	switch p.ip.z {
  1471  	case z0:
  1472  	case z4:
  1473  		max = len("255.255.255.255/32")
  1474  	default:
  1475  		max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0/128")
  1476  	}
  1477  	b := make([]byte, 0, max)
  1478  	b = p.AppendTo(b)
  1479  	return b, nil
  1480  }
  1481  
  1482  // UnmarshalText implements the encoding.TextUnmarshaler interface.
  1483  // The IP address is expected in a form accepted by [ParsePrefix]
  1484  // or generated by [Prefix.MarshalText].
  1485  func (p *Prefix) UnmarshalText(text []byte) error {
  1486  	if len(text) == 0 {
  1487  		*p = Prefix{}
  1488  		return nil
  1489  	}
  1490  	var err error
  1491  	*p, err = ParsePrefix(string(text))
  1492  	return err
  1493  }
  1494  
  1495  // MarshalBinary implements the [encoding.BinaryMarshaler] interface.
  1496  // It returns [Addr.MarshalBinary] with an additional byte appended
  1497  // containing the prefix bits.
  1498  func (p Prefix) MarshalBinary() ([]byte, error) {
  1499  	b := p.Addr().withoutZone().marshalBinaryWithTrailingBytes(1)
  1500  	b[len(b)-1] = uint8(p.Bits())
  1501  	return b, nil
  1502  }
  1503  
  1504  // UnmarshalBinary implements the [encoding.BinaryUnmarshaler] interface.
  1505  // It expects data in the form generated by [Prefix.MarshalBinary].
  1506  func (p *Prefix) UnmarshalBinary(b []byte) error {
  1507  	if len(b) < 1 {
  1508  		return errors.New("unexpected slice size")
  1509  	}
  1510  	var addr Addr
  1511  	err := addr.UnmarshalBinary(b[:len(b)-1])
  1512  	if err != nil {
  1513  		return err
  1514  	}
  1515  	*p = PrefixFrom(addr, int(b[len(b)-1]))
  1516  	return nil
  1517  }
  1518  
  1519  // String returns the CIDR notation of p: "<ip>/<bits>".
  1520  func (p Prefix) String() string {
  1521  	if !p.IsValid() {
  1522  		return "invalid Prefix"
  1523  	}
  1524  	return p.ip.String() + "/" + itoa.Itoa(p.Bits())
  1525  }
  1526  

View as plain text