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.
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
10 // Compared to the [net.IP] type, [Addr] type takes less memory, is immutable,
11 // and is comparable (supports == and being a map key).
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)
30 // Addr represents an IPv4 or IPv6 address (with or without a scoped
31 // addressing zone), similar to [net.IP] or [net.IPAddr].
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.
36 // The zero Addr is not a valid IP address.
37 // Addr{} is distinct from both 0.0.0.0 and ::.
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.
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.
46 // For example, 0011:2233:4455:6677:8899:aabb:ccdd:eeff is stored as:
47 // addr.hi = 0x0011223344556677
48 // addr.lo = 0x8899aabbccddeeff
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.
56 // z is a combination of the address family and the IPv6 zone.
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.
62 // Otherwise it's the interned zone name string.
66 // z0, z4, and z6noz are sentinel Addr.z values.
67 // See the Addr type's field docs.
69 z0 = (*intern.Value)(nil)
70 z4 = new(intern.Value)
71 z6noz = new(intern.Value)
74 // IPv6LinkLocalAllNodes returns the IPv6 link-local all nodes multicast
76 func IPv6LinkLocalAllNodes() Addr { return AddrFrom16([16]byte{0: 0xff, 1: 0x02, 15: 0x01}) }
78 // IPv6LinkLocalAllRouters returns the IPv6 link-local all routers multicast
80 func IPv6LinkLocalAllRouters() Addr { return AddrFrom16([16]byte{0: 0xff, 1: 0x02, 15: 0x02}) }
82 // IPv6Loopback returns the IPv6 loopback address ::1.
83 func IPv6Loopback() Addr { return AddrFrom16([16]byte{15: 0x01}) }
85 // IPv6Unspecified returns the IPv6 unspecified address "::".
86 func IPv6Unspecified() Addr { return Addr{z: z6noz} }
88 // IPv4Unspecified returns the IPv4 unspecified address "0.0.0.0".
89 func IPv4Unspecified() Addr { return AddrFrom4([4]byte{}) }
91 // AddrFrom4 returns the address of the IPv4 address given by the bytes in addr.
92 func AddrFrom4(addr [4]byte) Addr {
94 addr: uint128{0, 0xffff00000000 | uint64(addr[0])<<24 | uint64(addr[1])<<16 | uint64(addr[2])<<8 | uint64(addr[3])},
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 {
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++ {
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"}
128 return Addr{}, parseAddrError{in: s, msg: "unable to parse IP"}
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)
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.
147 func (err parseAddrError) Error() string {
150 return "ParseAddr(" + q(err.in) + "): " + err.msg + " (at " + q(err.at) + ")"
152 return "ParseAddr(" + q(err.in) + "): " + err.msg
155 // parseIPv4 parses s as an IPv4 address (in form "192.168.0.1").
156 func parseIPv4(s string) (ip Addr, err error) {
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"}
165 val = val*10 + int(s[i]) - '0'
168 return Addr{}, parseAddrError{in: s, msg: "IPv4 field has value >255"}
170 } else if s[i] == '.' {
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:]}
179 return Addr{}, parseAddrError{in: s, msg: "IPv4 address too long"}
181 fields[pos] = uint8(val)
186 return Addr{}, parseAddrError{in: s, msg: "unexpected character", at: s[i:]}
190 return Addr{}, parseAddrError{in: s, msg: "IPv4 address too short"}
192 fields[3] = uint8(val)
193 return AddrFrom4(fields), nil
196 // parseIPv6 parses s as an IPv6 address (in form "2001:db8::68").
197 func parseIPv6(in string) (Addr, error) {
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
205 i := bytealg.IndexByteString(s, '%')
207 s, zone = s[:i], s[i+1:]
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"}
215 ellipsis := -1 // position of ellipsis in ip
217 // Might have leading ellipsis
218 if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
221 // Might be only ellipsis
223 return IPv6Unspecified().WithZone(zone), nil
227 // Loop, parsing hex numbers followed by colon.
230 // Hex number. Similar to parseIPv4, inlining the hex number
231 // parsing yields a significant performance increase.
234 for ; off < len(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)
245 if acc > math.MaxUint16 {
247 return Addr{}, parseAddrError{in: in, msg: "IPv6 field has value >=2^16", at: s}
251 // No digits found, fail.
252 return Addr{}, parseAddrError{in: in, msg: "each colon-separated field must have at least one digit", at: s}
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}
263 return Addr{}, parseAddrError{in: in, msg: "too many hex fields to fit an embedded IPv4 at the end of the address", at: s}
265 // TODO: could make this a bit faster by having a helper
266 // that parses to a [4]byte, and have both parseIPv4 and
268 ip4, err := parseIPv4(s)
270 return Addr{}, parseAddrError{in: in, msg: err.Error(), at: s}
281 // Save this 16-bit chunk.
282 ip[i] = byte(acc >> 8)
286 // Stop at end of string.
292 // Otherwise must be followed by colon and more.
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}
300 // Look for ellipsis.
302 if ellipsis >= 0 { // already have one
303 return Addr{}, parseAddrError{in: in, msg: "multiple :: in address", at: s}
307 if len(s) == 0 { // can be at end
313 // Must have used entire string.
315 return Addr{}, parseAddrError{in: in, msg: "trailing garbage after address", at: s}
318 // If didn't parse enough, expand ellipsis.
321 return Addr{}, parseAddrError{in: in, msg: "address string too short"}
324 for j := i - 1; j >= ellipsis; j-- {
327 for j := ellipsis + n - 1; j >= ellipsis; j-- {
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"}
334 return AddrFrom16(ip).WithZone(zone), nil
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) {
343 return AddrFrom4([4]byte(slice)), true
345 return AddrFrom16([16]byte(slice)), true
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))
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))
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))
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.
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.
379 // IsValid reports whether the Addr is an initialized address (not the zero Addr).
381 // Note that "0.0.0.0" and "::" are both valid values.
382 func (ip Addr) IsValid() bool { return ip.z != z0 }
384 // BitLen returns the number of bits in the IP address:
385 // 128 for IPv6, 32 for IPv4, and 0 for the zero Addr.
387 // Note that IPv4-mapped IPv6 addresses are considered IPv6 addresses
388 // and therefore have bit length 128.
389 func (ip Addr) BitLen() int {
399 // Zone returns ip's IPv6 scoped addressing zone, if any.
400 func (ip Addr) Zone() string {
404 zone, _ := ip.z.Get().(string)
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 Less method.
411 func (ip Addr) Compare(ip2 Addr) int {
412 f1, f2 := ip.BitLen(), ip2.BitLen()
419 hi1, hi2 := ip.addr.hi, ip2.addr.hi
426 lo1, lo2 := ip.addr.lo, ip2.addr.lo
434 za, zb := ip.Zone(), ip2.Zone()
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 }
450 // Is4 reports whether ip is an IPv4 address.
452 // It returns false for IPv4-mapped IPv6 addresses. See Addr.Unmap.
453 func (ip Addr) Is4() bool {
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
462 // Is6 reports whether ip is an IPv6 address, including IPv4-mapped
464 func (ip Addr) Is6() bool {
465 return ip.z != z0 && ip.z != z4
468 // Unmap returns ip with any IPv4-mapped IPv6 address prefix removed.
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 {
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 {
490 ip.z = intern.GetByString(zone)
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 {
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
509 // IsLinkLocalUnicast reports whether ip is a link-local unicast address.
510 func (ip Addr) IsLinkLocalUnicast() bool {
511 // Dynamic Configuration of IPv4 Link-Local Addresses
512 // https://datatracker.ietf.org/doc/html/rfc3927#section-2.1
514 return ip.v4(0) == 169 && ip.v4(1) == 254
516 // IP Version 6 Addressing Architecture (2.4 Address Type Identification)
517 // https://datatracker.ietf.org/doc/html/rfc4291#section-2.4
519 return ip.v6u16(0)&0xffc0 == 0xfe80
521 return false // zero value
524 // IsLoopback reports whether ip is a loopback address.
525 func (ip Addr) IsLoopback() bool {
526 // Requirements for Internet Hosts -- Communication Layers (3.2.1.3 Addressing)
527 // https://datatracker.ietf.org/doc/html/rfc1122#section-3.2.1.3
529 return ip.v4(0) == 127
531 // IP Version 6 Addressing Architecture (2.4 Address Type Identification)
532 // https://datatracker.ietf.org/doc/html/rfc4291#section-2.4
534 return ip.addr.hi == 0 && ip.addr.lo == 1
536 return false // zero value
539 // IsMulticast reports whether ip is a multicast address.
540 func (ip Addr) IsMulticast() bool {
541 // Host Extensions for IP Multicasting (4. HOST GROUP ADDRESSES)
542 // https://datatracker.ietf.org/doc/html/rfc1112#section-4
544 return ip.v4(0)&0xf0 == 0xe0
546 // IP Version 6 Addressing Architecture (2.4 Address Type Identification)
547 // https://datatracker.ietf.org/doc/html/rfc4291#section-2.4
549 return ip.addr.hi>>(64-8) == 0xff // ip.v6(0) == 0xff
551 return false // zero value
554 // IsInterfaceLocalMulticast reports whether ip is an IPv6 interface-local
555 // multicast address.
556 func (ip Addr) IsInterfaceLocalMulticast() bool {
557 // IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses)
558 // https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1
560 return ip.v6u16(0)&0xff0f == 0xff01
562 return false // zero value
565 // IsLinkLocalMulticast reports whether ip is a link-local multicast address.
566 func (ip Addr) IsLinkLocalMulticast() bool {
567 // IPv4 Multicast Guidelines (4. Local Network Control Block (224.0.0/24))
568 // https://datatracker.ietf.org/doc/html/rfc5771#section-4
570 return ip.v4(0) == 224 && ip.v4(1) == 0 && ip.v4(2) == 0
572 // IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses)
573 // https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1
575 return ip.v6u16(0)&0xff0f == 0xff02
577 return false // zero value
580 // IsGlobalUnicast reports whether ip is a global unicast address.
582 // It returns true for IPv6 addresses which fall outside of the current
583 // IANA-allocated 2000::/3 global unicast space, with the exception of the
584 // link-local address space. It also returns true even if ip is in the IPv4
585 // private address space or IPv6 unique local address space.
586 // It returns false for the zero Addr.
588 // For reference, see RFC 1122, RFC 4291, and RFC 4632.
589 func (ip Addr) IsGlobalUnicast() bool {
591 // Invalid or zero-value.
595 // Match package net's IsGlobalUnicast logic. Notably private IPv4 addresses
596 // and ULA IPv6 addresses are still considered "global unicast".
597 if ip.Is4() && (ip == IPv4Unspecified() || ip == AddrFrom4([4]byte{255, 255, 255, 255})) {
601 return ip != IPv6Unspecified() &&
604 !ip.IsLinkLocalUnicast()
607 // IsPrivate reports whether ip is a private address, according to RFC 1918
608 // (IPv4 addresses) and RFC 4193 (IPv6 addresses). That is, it reports whether
609 // ip is in 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or fc00::/7. This is the
610 // same as net.IP.IsPrivate.
611 func (ip Addr) IsPrivate() bool {
612 // Match the stdlib's IsPrivate logic.
614 // RFC 1918 allocates 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 as
615 // private IPv4 address subnets.
616 return ip.v4(0) == 10 ||
617 (ip.v4(0) == 172 && ip.v4(1)&0xf0 == 16) ||
618 (ip.v4(0) == 192 && ip.v4(1) == 168)
622 // RFC 4193 allocates fc00::/7 as the unique local unicast IPv6 address
624 return ip.v6(0)&0xfe == 0xfc
627 return false // zero value
630 // IsUnspecified reports whether ip is an unspecified address, either the IPv4
631 // address "0.0.0.0" or the IPv6 address "::".
633 // Note that the zero Addr is not an unspecified address.
634 func (ip Addr) IsUnspecified() bool {
635 return ip == IPv4Unspecified() || ip == IPv6Unspecified()
638 // Prefix keeps only the top b bits of IP, producing a Prefix
639 // of the specified length.
640 // If ip is a zero Addr, Prefix always returns a zero Prefix and a nil error.
641 // Otherwise, if bits is less than zero or greater than ip.BitLen(),
642 // Prefix returns an error.
643 func (ip Addr) Prefix(b int) (Prefix, error) {
645 return Prefix{}, errors.New("negative Prefix bits")
653 return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv4")
658 return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv6")
661 ip.addr = ip.addr.and(mask6(effectiveBits))
662 return PrefixFrom(ip, b), nil
665 // As16 returns the IP address in its 16-byte representation.
666 // IPv4 addresses are returned as IPv4-mapped IPv6 addresses.
667 // IPv6 addresses with zones are returned without their zone (use the
668 // Zone method to get it).
669 // The ip zero value returns all zeroes.
670 func (ip Addr) As16() (a16 [16]byte) {
671 bePutUint64(a16[:8], ip.addr.hi)
672 bePutUint64(a16[8:], ip.addr.lo)
676 // As4 returns an IPv4 or IPv4-in-IPv6 address in its 4-byte representation.
677 // If ip is the zero Addr or an IPv6 address, As4 panics.
678 // Note that 0.0.0.0 is not the zero Addr.
679 func (ip Addr) As4() (a4 [4]byte) {
680 if ip.z == z4 || ip.Is4In6() {
681 bePutUint32(a4[:], uint32(ip.addr.lo))
685 panic("As4 called on IP zero value")
687 panic("As4 called on IPv6 address")
690 // AsSlice returns an IPv4 or IPv6 address in its respective 4-byte or 16-byte representation.
691 func (ip Addr) AsSlice() []byte {
697 bePutUint32(ret[:], uint32(ip.addr.lo))
701 bePutUint64(ret[:8], ip.addr.hi)
702 bePutUint64(ret[8:], ip.addr.lo)
707 // Next returns the address following ip.
708 // If there is none, it returns the zero Addr.
709 func (ip Addr) Next() Addr {
710 ip.addr = ip.addr.addOne()
712 if uint32(ip.addr.lo) == 0 {
717 if ip.addr.isZero() {
725 // Prev returns the IP before ip.
726 // If there is none, it returns the IP zero value.
727 func (ip Addr) Prev() Addr {
729 if uint32(ip.addr.lo) == 0 {
732 } else if ip.addr.isZero() {
735 ip.addr = ip.addr.subOne()
739 // String returns the string form of the IP address ip.
740 // It returns one of 5 forms:
742 // - "invalid IP", if ip is the zero Addr
743 // - IPv4 dotted decimal ("192.0.2.1")
744 // - IPv6 ("2001:db8::1")
745 // - "::ffff:1.2.3.4" (if Is4In6)
746 // - IPv6 with zone ("fe80:db8::1%eth0")
748 // Note that unlike package net's IP.String method,
749 // IPv4-mapped IPv6 addresses format with a "::ffff:"
750 // prefix before the dotted quad.
751 func (ip Addr) String() string {
759 if z := ip.Zone(); z != "" {
760 return "::ffff:" + ip.Unmap().string4() + "%" + z
762 return "::ffff:" + ip.Unmap().string4()
769 // AppendTo appends a text encoding of ip,
770 // as generated by MarshalText,
771 // to b and returns the extended buffer.
772 func (ip Addr) AppendTo(b []byte) []byte {
777 return ip.appendTo4(b)
780 b = append(b, "::ffff:"...)
781 b = ip.Unmap().appendTo4(b)
782 if z := ip.Zone(); z != "" {
788 return ip.appendTo6(b)
792 // digits is a string of the hex digits from 0 to f. It's used in
793 // appendDecimal and appendHex to format IP addresses.
794 const digits = "0123456789abcdef"
796 // appendDecimal appends the decimal string representation of x to b.
797 func appendDecimal(b []byte, x uint8) []byte {
798 // Using this function rather than strconv.AppendUint makes IPv4
799 // string building 2x faster.
802 b = append(b, digits[x/100])
805 b = append(b, digits[x/10%10])
807 return append(b, digits[x%10])
810 // appendHex appends the hex string representation of x to b.
811 func appendHex(b []byte, x uint16) []byte {
812 // Using this function rather than strconv.AppendUint makes IPv6
813 // string building 2x faster.
816 b = append(b, digits[x>>12])
819 b = append(b, digits[x>>8&0xf])
822 b = append(b, digits[x>>4&0xf])
824 return append(b, digits[x&0xf])
827 // appendHexPad appends the fully padded hex string representation of x to b.
828 func appendHexPad(b []byte, x uint16) []byte {
829 return append(b, digits[x>>12], digits[x>>8&0xf], digits[x>>4&0xf], digits[x&0xf])
832 func (ip Addr) string4() string {
833 const max = len("255.255.255.255")
834 ret := make([]byte, 0, max)
835 ret = ip.appendTo4(ret)
839 func (ip Addr) appendTo4(ret []byte) []byte {
840 ret = appendDecimal(ret, ip.v4(0))
841 ret = append(ret, '.')
842 ret = appendDecimal(ret, ip.v4(1))
843 ret = append(ret, '.')
844 ret = appendDecimal(ret, ip.v4(2))
845 ret = append(ret, '.')
846 ret = appendDecimal(ret, ip.v4(3))
850 // string6 formats ip in IPv6 textual representation. It follows the
851 // guidelines in section 4 of RFC 5952
852 // (https://tools.ietf.org/html/rfc5952#section-4): no unnecessary
853 // zeros, use :: to elide the longest run of zeros, and don't use ::
854 // to compact a single zero field.
855 func (ip Addr) string6() string {
856 // Use a zone with a "plausibly long" name, so that most zone-ful
857 // IP addresses won't require additional allocation.
859 // The compiler does a cool optimization here, where ret ends up
860 // stack-allocated and so the only allocation this function does
861 // is to construct the returned string. As such, it's okay to be a
862 // bit greedy here, size-wise.
863 const max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
864 ret := make([]byte, 0, max)
865 ret = ip.appendTo6(ret)
869 func (ip Addr) appendTo6(ret []byte) []byte {
870 zeroStart, zeroEnd := uint8(255), uint8(255)
871 for i := uint8(0); i < 8; i++ {
873 for j < 8 && ip.v6u16(j) == 0 {
876 if l := j - i; l >= 2 && l > zeroEnd-zeroStart {
877 zeroStart, zeroEnd = i, j
881 for i := uint8(0); i < 8; i++ {
883 ret = append(ret, ':', ':')
889 ret = append(ret, ':')
892 ret = appendHex(ret, ip.v6u16(i))
896 ret = append(ret, '%')
897 ret = append(ret, ip.Zone()...)
902 // StringExpanded is like String but IPv6 addresses are expanded with leading
903 // zeroes and no "::" compression. For example, "2001:db8::1" becomes
904 // "2001:0db8:0000:0000:0000:0000:0000:0001".
905 func (ip Addr) StringExpanded() string {
911 const size = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
912 ret := make([]byte, 0, size)
913 for i := uint8(0); i < 8; i++ {
915 ret = append(ret, ':')
918 ret = appendHexPad(ret, ip.v6u16(i))
922 // The addition of a zone will cause a second allocation, but when there
923 // is no zone the ret slice will be stack allocated.
924 ret = append(ret, '%')
925 ret = append(ret, ip.Zone()...)
930 // MarshalText implements the encoding.TextMarshaler interface,
931 // The encoding is the same as returned by String, with one exception:
932 // If ip is the zero Addr, the encoding is the empty string.
933 func (ip Addr) MarshalText() ([]byte, error) {
936 return []byte(""), nil
938 max := len("255.255.255.255")
939 b := make([]byte, 0, max)
940 return ip.appendTo4(b), nil
942 max := len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
943 b := make([]byte, 0, max)
945 b = append(b, "::ffff:"...)
946 b = ip.Unmap().appendTo4(b)
947 if z := ip.Zone(); z != "" {
953 return ip.appendTo6(b), nil
958 // UnmarshalText implements the encoding.TextUnmarshaler interface.
959 // The IP address is expected in a form accepted by ParseAddr.
961 // If text is empty, UnmarshalText sets *ip to the zero Addr and
963 func (ip *Addr) UnmarshalText(text []byte) error {
969 *ip, err = ParseAddr(string(text))
973 func (ip Addr) marshalBinaryWithTrailingBytes(trailingBytes int) []byte {
977 b = make([]byte, trailingBytes)
979 b = make([]byte, 4+trailingBytes)
980 bePutUint32(b, uint32(ip.addr.lo))
983 b = make([]byte, 16+len(z)+trailingBytes)
984 bePutUint64(b[:8], ip.addr.hi)
985 bePutUint64(b[8:], ip.addr.lo)
991 // MarshalBinary implements the encoding.BinaryMarshaler interface.
992 // It returns a zero-length slice for the zero Addr,
993 // the 4-byte form for an IPv4 address,
994 // and the 16-byte form with zone appended for an IPv6 address.
995 func (ip Addr) MarshalBinary() ([]byte, error) {
996 return ip.marshalBinaryWithTrailingBytes(0), nil
999 // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
1000 // It expects data in the form generated by MarshalBinary.
1001 func (ip *Addr) UnmarshalBinary(b []byte) error {
1008 *ip = AddrFrom4([4]byte(b))
1011 *ip = AddrFrom16([16]byte(b))
1014 *ip = AddrFrom16([16]byte(b[:16])).WithZone(string(b[16:]))
1017 return errors.New("unexpected slice size")
1020 // AddrPort is an IP and a port number.
1021 type AddrPort struct {
1026 // AddrPortFrom returns an AddrPort with the provided IP and port.
1027 // It does not allocate.
1028 func AddrPortFrom(ip Addr, port uint16) AddrPort { return AddrPort{ip: ip, port: port} }
1030 // Addr returns p's IP address.
1031 func (p AddrPort) Addr() Addr { return p.ip }
1033 // Port returns p's port.
1034 func (p AddrPort) Port() uint16 { return p.port }
1036 // splitAddrPort splits s into an IP address string and a port
1037 // string. It splits strings shaped like "foo:bar" or "[foo]:bar",
1038 // without further validating the substrings. v6 indicates whether the
1039 // ip string should parse as an IPv6 address or an IPv4 address, in
1040 // order for s to be a valid ip:port string.
1041 func splitAddrPort(s string) (ip, port string, v6 bool, err error) {
1042 i := bytealg.LastIndexByteString(s, ':')
1044 return "", "", false, errors.New("not an ip:port")
1047 ip, port = s[:i], s[i+1:]
1049 return "", "", false, errors.New("no IP")
1052 return "", "", false, errors.New("no port")
1055 if len(ip) < 2 || ip[len(ip)-1] != ']' {
1056 return "", "", false, errors.New("missing ]")
1058 ip = ip[1 : len(ip)-1]
1062 return ip, port, v6, nil
1065 // ParseAddrPort parses s as an AddrPort.
1067 // It doesn't do any name resolution: both the address and the port
1069 func ParseAddrPort(s string) (AddrPort, error) {
1071 ip, port, v6, err := splitAddrPort(s)
1075 port16, err := strconv.ParseUint(port, 10, 16)
1077 return ipp, errors.New("invalid port " + strconv.Quote(port) + " parsing " + strconv.Quote(s))
1079 ipp.port = uint16(port16)
1080 ipp.ip, err = ParseAddr(ip)
1082 return AddrPort{}, err
1084 if v6 && ipp.ip.Is4() {
1085 return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", square brackets can only be used with IPv6 addresses")
1086 } else if !v6 && ipp.ip.Is6() {
1087 return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", IPv6 addresses must be surrounded by square brackets")
1092 // MustParseAddrPort calls ParseAddrPort(s) and panics on error.
1093 // It is intended for use in tests with hard-coded strings.
1094 func MustParseAddrPort(s string) AddrPort {
1095 ip, err := ParseAddrPort(s)
1102 // IsValid reports whether p.Addr() is valid.
1103 // All ports are valid, including zero.
1104 func (p AddrPort) IsValid() bool { return p.ip.IsValid() }
1106 // Compare returns an integer comparing two AddrPorts.
1107 // The result will be 0 if p == p2, -1 if p < p2, and +1 if p > p2.
1108 // AddrPorts sort first by IP address, then port.
1109 func (p AddrPort) Compare(p2 AddrPort) int {
1110 if c := p.Addr().Compare(p2.Addr()); c != 0 {
1113 return cmp.Compare(p.Port(), p2.Port())
1116 func (p AddrPort) String() string {
1119 return "invalid AddrPort"
1122 buf := make([]byte, 0, 21)
1124 buf = strconv.AppendUint(buf, uint64(a[i]), 10)
1125 buf = append(buf, "...:"[i])
1127 buf = strconv.AppendUint(buf, uint64(p.port), 10)
1130 // TODO: this could be more efficient allocation-wise:
1131 return joinHostPort(p.ip.String(), itoa.Itoa(int(p.port)))
1135 func joinHostPort(host, port string) string {
1136 // We assume that host is a literal IPv6 address if host has
1138 if bytealg.IndexByteString(host, ':') >= 0 {
1139 return "[" + host + "]:" + port
1141 return host + ":" + port
1144 // AppendTo appends a text encoding of p,
1145 // as generated by MarshalText,
1146 // to b and returns the extended buffer.
1147 func (p AddrPort) AppendTo(b []byte) []byte {
1152 b = p.ip.appendTo4(b)
1155 b = append(b, "[::ffff:"...)
1156 b = p.ip.Unmap().appendTo4(b)
1157 if z := p.ip.Zone(); z != "" {
1163 b = p.ip.appendTo6(b)
1168 b = strconv.AppendUint(b, uint64(p.port), 10)
1172 // MarshalText implements the encoding.TextMarshaler interface. The
1173 // encoding is the same as returned by String, with one exception: if
1174 // p.Addr() is the zero Addr, the encoding is the empty string.
1175 func (p AddrPort) MarshalText() ([]byte, error) {
1180 max = len("255.255.255.255:65535")
1182 max = len("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0]:65535")
1184 b := make([]byte, 0, max)
1189 // UnmarshalText implements the encoding.TextUnmarshaler
1190 // interface. The AddrPort is expected in a form
1191 // generated by MarshalText or accepted by ParseAddrPort.
1192 func (p *AddrPort) UnmarshalText(text []byte) error {
1198 *p, err = ParseAddrPort(string(text))
1202 // MarshalBinary implements the encoding.BinaryMarshaler interface.
1203 // It returns Addr.MarshalBinary with an additional two bytes appended
1204 // containing the port in little-endian.
1205 func (p AddrPort) MarshalBinary() ([]byte, error) {
1206 b := p.Addr().marshalBinaryWithTrailingBytes(2)
1207 lePutUint16(b[len(b)-2:], p.Port())
1211 // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
1212 // It expects data in the form generated by MarshalBinary.
1213 func (p *AddrPort) UnmarshalBinary(b []byte) error {
1215 return errors.New("unexpected slice size")
1218 err := addr.UnmarshalBinary(b[:len(b)-2])
1222 *p = AddrPortFrom(addr, leUint16(b[len(b)-2:]))
1226 // Prefix is an IP address prefix (CIDR) representing an IP network.
1228 // The first Bits() of Addr() are specified. The remaining bits match any address.
1229 // The range of Bits() is [0,32] for IPv4 or [0,128] for IPv6.
1230 type Prefix struct {
1233 // bitsPlusOne stores the prefix bit length plus one.
1234 // A Prefix is valid if and only if bitsPlusOne is non-zero.
1238 // PrefixFrom returns a Prefix with the provided IP address and bit
1241 // It does not allocate. Unlike Addr.Prefix, PrefixFrom does not mask
1242 // off the host bits of ip.
1244 // If bits is less than zero or greater than ip.BitLen, Prefix.Bits
1245 // will return an invalid value -1.
1246 func PrefixFrom(ip Addr, bits int) Prefix {
1247 var bitsPlusOne uint8
1248 if !ip.isZero() && bits >= 0 && bits <= ip.BitLen() {
1249 bitsPlusOne = uint8(bits) + 1
1252 ip: ip.withoutZone(),
1253 bitsPlusOne: bitsPlusOne,
1257 // Addr returns p's IP address.
1258 func (p Prefix) Addr() Addr { return p.ip }
1260 // Bits returns p's prefix length.
1262 // It reports -1 if invalid.
1263 func (p Prefix) Bits() int { return int(p.bitsPlusOne) - 1 }
1265 // IsValid reports whether p.Bits() has a valid range for p.Addr().
1266 // If p.Addr() is the zero Addr, IsValid returns false.
1267 // Note that if p is the zero Prefix, then p.IsValid() == false.
1268 func (p Prefix) IsValid() bool { return p.bitsPlusOne > 0 }
1270 func (p Prefix) isZero() bool { return p == Prefix{} }
1272 // IsSingleIP reports whether p contains exactly one IP.
1273 func (p Prefix) IsSingleIP() bool { return p.IsValid() && p.Bits() == p.ip.BitLen() }
1275 // Compare returns an integer comparing two prefixes.
1276 // The result will be 0 if p == p2, -1 if p < p2, and +1 if p > p2.
1277 // Prefixes sort first by validity (invalid before valid), then
1278 // address family (IPv4 before IPv6), then prefix length, then
1280 func (p Prefix) Compare(p2 Prefix) int {
1281 if c := cmp.Compare(p.Addr().BitLen(), p2.Addr().BitLen()); c != 0 {
1284 if c := cmp.Compare(p.Bits(), p2.Bits()); c != 0 {
1287 return p.Addr().Compare(p2.Addr())
1290 // ParsePrefix parses s as an IP address prefix.
1291 // The string can be in the form "192.168.1.0/24" or "2001:db8::/32",
1292 // the CIDR notation defined in RFC 4632 and RFC 4291.
1293 // IPv6 zones are not permitted in prefixes, and an error will be returned if a
1296 // Note that masked address bits are not zeroed. Use Masked for that.
1297 func ParsePrefix(s string) (Prefix, error) {
1298 i := bytealg.LastIndexByteString(s, '/')
1300 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): no '/'")
1302 ip, err := ParseAddr(s[:i])
1304 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): " + err.Error())
1306 // IPv6 zones are not allowed: https://go.dev/issue/51899
1307 if ip.Is6() && ip.z != z6noz {
1308 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): IPv6 zones cannot be present in a prefix")
1312 bits, err := strconv.Atoi(bitsStr)
1314 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): bad bits after slash: " + strconv.Quote(bitsStr))
1320 if bits < 0 || bits > maxBits {
1321 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): prefix length out of range")
1323 return PrefixFrom(ip, bits), nil
1326 // MustParsePrefix calls ParsePrefix(s) and panics on error.
1327 // It is intended for use in tests with hard-coded strings.
1328 func MustParsePrefix(s string) Prefix {
1329 ip, err := ParsePrefix(s)
1336 // Masked returns p in its canonical form, with all but the high
1337 // p.Bits() bits of p.Addr() masked off.
1339 // If p is zero or otherwise invalid, Masked returns the zero Prefix.
1340 func (p Prefix) Masked() Prefix {
1341 m, _ := p.ip.Prefix(p.Bits())
1345 // Contains reports whether the network p includes ip.
1347 // An IPv4 address will not match an IPv6 prefix.
1348 // An IPv4-mapped IPv6 address will not match an IPv4 prefix.
1349 // A zero-value IP will not match any prefix.
1350 // If ip has an IPv6 zone, Contains returns false,
1351 // because Prefixes strip zones.
1352 func (p Prefix) Contains(ip Addr) bool {
1353 if !p.IsValid() || ip.hasZone() {
1356 if f1, f2 := p.ip.BitLen(), ip.BitLen(); f1 == 0 || f2 == 0 || f1 != f2 {
1360 // xor the IP addresses together; mismatched bits are now ones.
1361 // Shift away the number of bits we don't care about.
1362 // Shifts in Go are more efficient if the compiler can prove
1363 // that the shift amount is smaller than the width of the shifted type (64 here).
1364 // We know that p.bits is in the range 0..32 because p is Valid;
1365 // the compiler doesn't know that, so mask with 63 to help it.
1366 // Now truncate to 32 bits, because this is IPv4.
1367 // If all the bits we care about are equal, the result will be zero.
1368 return uint32((ip.addr.lo^p.ip.addr.lo)>>((32-p.Bits())&63)) == 0
1370 // xor the IP addresses together.
1371 // Mask away the bits we don't care about.
1372 // If all the bits we care about are equal, the result will be zero.
1373 return ip.addr.xor(p.ip.addr).and(mask6(p.Bits())).isZero()
1377 // Overlaps reports whether p and o contain any IP addresses in common.
1379 // If p and o are of different address families or either have a zero
1380 // IP, it reports false. Like the Contains method, a prefix with an
1381 // IPv4-mapped IPv6 address is still treated as an IPv6 mask.
1382 func (p Prefix) Overlaps(o Prefix) bool {
1383 if !p.IsValid() || !o.IsValid() {
1389 if p.ip.Is4() != o.ip.Is4() {
1393 if pb, ob := p.Bits(), o.Bits(); pb < ob {
1401 // One of these Prefix calls might look redundant, but we don't require
1402 // that p and o values are normalized (via Prefix.Masked) first,
1403 // so the Prefix call on the one that's already minBits serves to zero
1404 // out any remaining bits in IP.
1406 if p, err = p.ip.Prefix(minBits); err != nil {
1409 if o, err = o.ip.Prefix(minBits); err != nil {
1415 // AppendTo appends a text encoding of p,
1416 // as generated by MarshalText,
1417 // to b and returns the extended buffer.
1418 func (p Prefix) AppendTo(b []byte) []byte {
1423 return append(b, "invalid Prefix"...)
1426 // p.ip is non-nil, because p is valid.
1428 b = p.ip.appendTo4(b)
1431 b = append(b, "::ffff:"...)
1432 b = p.ip.Unmap().appendTo4(b)
1434 b = p.ip.appendTo6(b)
1439 b = appendDecimal(b, uint8(p.Bits()))
1443 // MarshalText implements the encoding.TextMarshaler interface,
1444 // The encoding is the same as returned by String, with one exception:
1445 // If p is the zero value, the encoding is the empty string.
1446 func (p Prefix) MarshalText() ([]byte, error) {
1451 max = len("255.255.255.255/32")
1453 max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0/128")
1455 b := make([]byte, 0, max)
1460 // UnmarshalText implements the encoding.TextUnmarshaler interface.
1461 // The IP address is expected in a form accepted by ParsePrefix
1462 // or generated by MarshalText.
1463 func (p *Prefix) UnmarshalText(text []byte) error {
1469 *p, err = ParsePrefix(string(text))
1473 // MarshalBinary implements the encoding.BinaryMarshaler interface.
1474 // It returns Addr.MarshalBinary with an additional byte appended
1475 // containing the prefix bits.
1476 func (p Prefix) MarshalBinary() ([]byte, error) {
1477 b := p.Addr().withoutZone().marshalBinaryWithTrailingBytes(1)
1478 b[len(b)-1] = uint8(p.Bits())
1482 // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
1483 // It expects data in the form generated by MarshalBinary.
1484 func (p *Prefix) UnmarshalBinary(b []byte) error {
1486 return errors.New("unexpected slice size")
1489 err := addr.UnmarshalBinary(b[:len(b)-1])
1493 *p = PrefixFrom(addr, int(b[len(b)-1]))
1497 // String returns the CIDR notation of p: "<ip>/<bits>".
1498 func (p Prefix) String() string {
1500 return "invalid Prefix"
1502 return p.ip.String() + "/" + itoa.Itoa(p.Bits())