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

View as plain text