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).
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)
29 // Addr represents an IPv4 or IPv6 address (with or without a scoped
30 // addressing zone), similar to [net.IP] or [net.IPAddr].
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.
35 // The zero Addr is not a valid IP address.
36 // Addr{} is distinct from both 0.0.0.0 and ::.
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.
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.
45 // For example, 0011:2233:4455:6677:8899:aabb:ccdd:eeff is stored as:
46 // addr.hi = 0x0011223344556677
47 // addr.lo = 0x8899aabbccddeeff
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.
55 // z is a combination of the address family and the IPv6 zone.
57 // nil means invalid IP address (for a zero Addr).
58 // z4 means an IPv4 address.
59 // z6noz means an IPv6 address without a zone.
61 // Otherwise it's the interned zone name string.
65 // z0, z4, and z6noz are sentinel Addr.z values.
66 // See the Addr type's field docs.
68 z0 = (*intern.Value)(nil)
69 z4 = new(intern.Value)
70 z6noz = new(intern.Value)
73 // IPv6LinkLocalAllNodes returns the IPv6 link-local all nodes multicast
75 func IPv6LinkLocalAllNodes() Addr { return AddrFrom16([16]byte{0: 0xff, 1: 0x02, 15: 0x01}) }
77 // IPv6LinkLocalAllRouters returns the IPv6 link-local all routers multicast
79 func IPv6LinkLocalAllRouters() Addr { return AddrFrom16([16]byte{0: 0xff, 1: 0x02, 15: 0x02}) }
81 // IPv6Loopback returns the IPv6 loopback address ::1.
82 func IPv6Loopback() Addr { return AddrFrom16([16]byte{15: 0x01}) }
84 // IPv6Unspecified returns the IPv6 unspecified address "::".
85 func IPv6Unspecified() Addr { return Addr{z: z6noz} }
87 // IPv4Unspecified returns the IPv4 unspecified address "0.0.0.0".
88 func IPv4Unspecified() Addr { return AddrFrom4([4]byte{}) }
90 // AddrFrom4 returns the address of the IPv4 address given by the bytes in addr.
91 func AddrFrom4(addr [4]byte) Addr {
93 addr: uint128{0, 0xffff00000000 | uint64(addr[0])<<24 | uint64(addr[1])<<16 | uint64(addr[2])<<8 | uint64(addr[3])},
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 {
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++ {
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"}
127 return Addr{}, parseAddrError{in: s, msg: "unable to parse IP"}
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)
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.
146 func (err parseAddrError) Error() string {
149 return "ParseAddr(" + q(err.in) + "): " + err.msg + " (at " + q(err.at) + ")"
151 return "ParseAddr(" + q(err.in) + "): " + err.msg
154 // parseIPv4 parses s as an IPv4 address (in form "192.168.0.1").
155 func parseIPv4(s string) (ip Addr, err error) {
158 var digLen int // number of digits in current octet
159 for i := 0; i < len(s); i++ {
160 if s[i] >= '0' && s[i] <= '9' {
161 if digLen == 1 && val == 0 {
162 return Addr{}, parseAddrError{in: s, msg: "IPv4 field has octet with leading zero"}
164 val = val*10 + int(s[i]) - '0'
167 return Addr{}, parseAddrError{in: s, msg: "IPv4 field has value >255"}
169 } else if s[i] == '.' {
173 if i == 0 || i == len(s)-1 || s[i-1] == '.' {
174 return Addr{}, parseAddrError{in: s, msg: "IPv4 field must have at least one digit", at: s[i:]}
178 return Addr{}, parseAddrError{in: s, msg: "IPv4 address too long"}
180 fields[pos] = uint8(val)
185 return Addr{}, parseAddrError{in: s, msg: "unexpected character", at: s[i:]}
189 return Addr{}, parseAddrError{in: s, msg: "IPv4 address too short"}
191 fields[3] = uint8(val)
192 return AddrFrom4(fields), nil
195 // parseIPv6 parses s as an IPv6 address (in form "2001:db8::68").
196 func parseIPv6(in string) (Addr, error) {
199 // Split off the zone right from the start. Yes it's a second scan
200 // of the string, but trying to handle it inline makes a bunch of
201 // other inner loop conditionals more expensive, and it ends up
204 i := bytealg.IndexByteString(s, '%')
206 s, zone = s[:i], s[i+1:]
208 // Not allowed to have an empty zone if explicitly specified.
209 return Addr{}, parseAddrError{in: in, msg: "zone must be a non-empty string"}
214 ellipsis := -1 // position of ellipsis in ip
216 // Might have leading ellipsis
217 if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
220 // Might be only ellipsis
222 return IPv6Unspecified().WithZone(zone), nil
226 // Loop, parsing hex numbers followed by colon.
229 // Hex number. Similar to parseIPv4, inlining the hex number
230 // parsing yields a significant performance increase.
233 for ; off < len(s); off++ {
235 if c >= '0' && c <= '9' {
236 acc = (acc << 4) + uint32(c-'0')
237 } else if c >= 'a' && c <= 'f' {
238 acc = (acc << 4) + uint32(c-'a'+10)
239 } else if c >= 'A' && c <= 'F' {
240 acc = (acc << 4) + uint32(c-'A'+10)
244 if acc > math.MaxUint16 {
246 return Addr{}, parseAddrError{in: in, msg: "IPv6 field has value >=2^16", at: s}
250 // No digits found, fail.
251 return Addr{}, parseAddrError{in: in, msg: "each colon-separated field must have at least one digit", at: s}
254 // If followed by dot, might be in trailing IPv4.
255 if off < len(s) && s[off] == '.' {
256 if ellipsis < 0 && i != 12 {
257 // Not the right place.
258 return Addr{}, parseAddrError{in: in, msg: "embedded IPv4 address must replace the final 2 fields of the address", at: s}
262 return Addr{}, parseAddrError{in: in, msg: "too many hex fields to fit an embedded IPv4 at the end of the address", at: s}
264 // TODO: could make this a bit faster by having a helper
265 // that parses to a [4]byte, and have both parseIPv4 and
267 ip4, err := parseIPv4(s)
269 return Addr{}, parseAddrError{in: in, msg: err.Error(), at: s}
280 // Save this 16-bit chunk.
281 ip[i] = byte(acc >> 8)
285 // Stop at end of string.
291 // Otherwise must be followed by colon and more.
293 return Addr{}, parseAddrError{in: in, msg: "unexpected character, want colon", at: s}
294 } else if len(s) == 1 {
295 return Addr{}, parseAddrError{in: in, msg: "colon must be followed by more characters", at: s}
299 // Look for ellipsis.
301 if ellipsis >= 0 { // already have one
302 return Addr{}, parseAddrError{in: in, msg: "multiple :: in address", at: s}
306 if len(s) == 0 { // can be at end
312 // Must have used entire string.
314 return Addr{}, parseAddrError{in: in, msg: "trailing garbage after address", at: s}
317 // If didn't parse enough, expand ellipsis.
320 return Addr{}, parseAddrError{in: in, msg: "address string too short"}
323 for j := i - 1; j >= ellipsis; j-- {
326 for j := ellipsis + n - 1; j >= ellipsis; j-- {
329 } else if ellipsis >= 0 {
330 // Ellipsis must represent at least one 0 group.
331 return Addr{}, parseAddrError{in: in, msg: "the :: must expand to at least one field of zeros"}
333 return AddrFrom16(ip).WithZone(zone), nil
336 // AddrFromSlice parses the 4- or 16-byte byte slice as an IPv4 or IPv6 address.
337 // Note that a net.IP can be passed directly as the []byte argument.
338 // If slice's length is not 4 or 16, AddrFromSlice returns Addr{}, false.
339 func AddrFromSlice(slice []byte) (ip Addr, ok bool) {
342 return AddrFrom4([4]byte(slice)), true
344 return AddrFrom16([16]byte(slice)), true
349 // v4 returns the i'th byte of ip. If ip is not an IPv4, v4 returns
350 // unspecified garbage.
351 func (ip Addr) v4(i uint8) uint8 {
352 return uint8(ip.addr.lo >> ((3 - i) * 8))
355 // v6 returns the i'th byte of ip. If ip is an IPv4 address, this
356 // accesses the IPv4-mapped IPv6 address form of the IP.
357 func (ip Addr) v6(i uint8) uint8 {
358 return uint8(*(ip.addr.halves()[(i/8)%2]) >> ((7 - i%8) * 8))
361 // v6u16 returns the i'th 16-bit word of ip. If ip is an IPv4 address,
362 // this accesses the IPv4-mapped IPv6 address form of the IP.
363 func (ip Addr) v6u16(i uint8) uint16 {
364 return uint16(*(ip.addr.halves()[(i/4)%2]) >> ((3 - i%4) * 16))
367 // isZero reports whether ip is the zero value of the IP type.
368 // The zero value is not a valid IP address of any type.
370 // Note that "0.0.0.0" and "::" are not the zero value. Use IsUnspecified to
371 // check for these values instead.
372 func (ip Addr) isZero() bool {
373 // Faster than comparing ip == Addr{}, but effectively equivalent,
374 // as there's no way to make an IP with a nil z from this package.
378 // IsValid reports whether the Addr is an initialized address (not the zero Addr).
380 // Note that "0.0.0.0" and "::" are both valid values.
381 func (ip Addr) IsValid() bool { return ip.z != z0 }
383 // BitLen returns the number of bits in the IP address:
384 // 128 for IPv6, 32 for IPv4, and 0 for the zero Addr.
386 // Note that IPv4-mapped IPv6 addresses are considered IPv6 addresses
387 // and therefore have bit length 128.
388 func (ip Addr) BitLen() int {
398 // Zone returns ip's IPv6 scoped addressing zone, if any.
399 func (ip Addr) Zone() string {
403 zone, _ := ip.z.Get().(string)
407 // Compare returns an integer comparing two IPs.
408 // The result will be 0 if ip == ip2, -1 if ip < ip2, and +1 if ip > ip2.
409 // The definition of "less than" is the same as the Less method.
410 func (ip Addr) Compare(ip2 Addr) int {
411 f1, f2 := ip.BitLen(), ip2.BitLen()
418 hi1, hi2 := ip.addr.hi, ip2.addr.hi
425 lo1, lo2 := ip.addr.lo, ip2.addr.lo
433 za, zb := ip.Zone(), ip2.Zone()
444 // Less reports whether ip sorts before ip2.
445 // IP addresses sort first by length, then their address.
446 // IPv6 addresses with zones sort just after the same address without a zone.
447 func (ip Addr) Less(ip2 Addr) bool { return ip.Compare(ip2) == -1 }
449 // Is4 reports whether ip is an IPv4 address.
451 // It returns false for IPv4-mapped IPv6 addresses. See Addr.Unmap.
452 func (ip Addr) Is4() bool {
456 // Is4In6 reports whether ip is an IPv4-mapped IPv6 address.
457 func (ip Addr) Is4In6() bool {
458 return ip.Is6() && ip.addr.hi == 0 && ip.addr.lo>>32 == 0xffff
461 // Is6 reports whether ip is an IPv6 address, including IPv4-mapped
463 func (ip Addr) Is6() bool {
464 return ip.z != z0 && ip.z != z4
467 // Unmap returns ip with any IPv4-mapped IPv6 address prefix removed.
469 // That is, if ip is an IPv6 address wrapping an IPv4 address, it
470 // returns the wrapped IPv4 address. Otherwise it returns ip unmodified.
471 func (ip Addr) Unmap() Addr {
478 // WithZone returns an IP that's the same as ip but with the provided
479 // zone. If zone is empty, the zone is removed. If ip is an IPv4
480 // address, WithZone is a no-op and returns ip unchanged.
481 func (ip Addr) WithZone(zone string) Addr {
489 ip.z = intern.GetByString(zone)
493 // withoutZone unconditionally strips the zone from ip.
494 // It's similar to WithZone, but small enough to be inlinable.
495 func (ip Addr) withoutZone() Addr {
503 // hasZone reports whether ip has an IPv6 zone.
504 func (ip Addr) hasZone() bool {
505 return ip.z != z0 && ip.z != z4 && ip.z != z6noz
508 // IsLinkLocalUnicast reports whether ip is a link-local unicast address.
509 func (ip Addr) IsLinkLocalUnicast() bool {
510 // Dynamic Configuration of IPv4 Link-Local Addresses
511 // https://datatracker.ietf.org/doc/html/rfc3927#section-2.1
513 return ip.v4(0) == 169 && ip.v4(1) == 254
515 // IP Version 6 Addressing Architecture (2.4 Address Type Identification)
516 // https://datatracker.ietf.org/doc/html/rfc4291#section-2.4
518 return ip.v6u16(0)&0xffc0 == 0xfe80
520 return false // zero value
523 // IsLoopback reports whether ip is a loopback address.
524 func (ip Addr) IsLoopback() bool {
525 // Requirements for Internet Hosts -- Communication Layers (3.2.1.3 Addressing)
526 // https://datatracker.ietf.org/doc/html/rfc1122#section-3.2.1.3
528 return ip.v4(0) == 127
530 // IP Version 6 Addressing Architecture (2.4 Address Type Identification)
531 // https://datatracker.ietf.org/doc/html/rfc4291#section-2.4
533 return ip.addr.hi == 0 && ip.addr.lo == 1
535 return false // zero value
538 // IsMulticast reports whether ip is a multicast address.
539 func (ip Addr) IsMulticast() bool {
540 // Host Extensions for IP Multicasting (4. HOST GROUP ADDRESSES)
541 // https://datatracker.ietf.org/doc/html/rfc1112#section-4
543 return ip.v4(0)&0xf0 == 0xe0
545 // IP Version 6 Addressing Architecture (2.4 Address Type Identification)
546 // https://datatracker.ietf.org/doc/html/rfc4291#section-2.4
548 return ip.addr.hi>>(64-8) == 0xff // ip.v6(0) == 0xff
550 return false // zero value
553 // IsInterfaceLocalMulticast reports whether ip is an IPv6 interface-local
554 // multicast address.
555 func (ip Addr) IsInterfaceLocalMulticast() bool {
556 // IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses)
557 // https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1
559 return ip.v6u16(0)&0xff0f == 0xff01
561 return false // zero value
564 // IsLinkLocalMulticast reports whether ip is a link-local multicast address.
565 func (ip Addr) IsLinkLocalMulticast() bool {
566 // IPv4 Multicast Guidelines (4. Local Network Control Block (224.0.0/24))
567 // https://datatracker.ietf.org/doc/html/rfc5771#section-4
569 return ip.v4(0) == 224 && ip.v4(1) == 0 && ip.v4(2) == 0
571 // IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses)
572 // https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1
574 return ip.v6u16(0)&0xff0f == 0xff02
576 return false // zero value
579 // IsGlobalUnicast reports whether ip is a global unicast address.
581 // It returns true for IPv6 addresses which fall outside of the current
582 // IANA-allocated 2000::/3 global unicast space, with the exception of the
583 // link-local address space. It also returns true even if ip is in the IPv4
584 // private address space or IPv6 unique local address space.
585 // It returns false for the zero Addr.
587 // For reference, see RFC 1122, RFC 4291, and RFC 4632.
588 func (ip Addr) IsGlobalUnicast() bool {
590 // Invalid or zero-value.
594 // Match package net's IsGlobalUnicast logic. Notably private IPv4 addresses
595 // and ULA IPv6 addresses are still considered "global unicast".
596 if ip.Is4() && (ip == IPv4Unspecified() || ip == AddrFrom4([4]byte{255, 255, 255, 255})) {
600 return ip != IPv6Unspecified() &&
603 !ip.IsLinkLocalUnicast()
606 // IsPrivate reports whether ip is a private address, according to RFC 1918
607 // (IPv4 addresses) and RFC 4193 (IPv6 addresses). That is, it reports whether
608 // ip is in 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or fc00::/7. This is the
609 // same as net.IP.IsPrivate.
610 func (ip Addr) IsPrivate() bool {
611 // Match the stdlib's IsPrivate logic.
613 // RFC 1918 allocates 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 as
614 // private IPv4 address subnets.
615 return ip.v4(0) == 10 ||
616 (ip.v4(0) == 172 && ip.v4(1)&0xf0 == 16) ||
617 (ip.v4(0) == 192 && ip.v4(1) == 168)
621 // RFC 4193 allocates fc00::/7 as the unique local unicast IPv6 address
623 return ip.v6(0)&0xfe == 0xfc
626 return false // zero value
629 // IsUnspecified reports whether ip is an unspecified address, either the IPv4
630 // address "0.0.0.0" or the IPv6 address "::".
632 // Note that the zero Addr is not an unspecified address.
633 func (ip Addr) IsUnspecified() bool {
634 return ip == IPv4Unspecified() || ip == IPv6Unspecified()
637 // Prefix keeps only the top b bits of IP, producing a Prefix
638 // of the specified length.
639 // If ip is a zero Addr, Prefix always returns a zero Prefix and a nil error.
640 // Otherwise, if bits is less than zero or greater than ip.BitLen(),
641 // Prefix returns an error.
642 func (ip Addr) Prefix(b int) (Prefix, error) {
644 return Prefix{}, errors.New("negative Prefix bits")
652 return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv4")
657 return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv6")
660 ip.addr = ip.addr.and(mask6(effectiveBits))
661 return PrefixFrom(ip, b), nil
664 // As16 returns the IP address in its 16-byte representation.
665 // IPv4 addresses are returned as IPv4-mapped IPv6 addresses.
666 // IPv6 addresses with zones are returned without their zone (use the
667 // Zone method to get it).
668 // The ip zero value returns all zeroes.
669 func (ip Addr) As16() (a16 [16]byte) {
670 bePutUint64(a16[:8], ip.addr.hi)
671 bePutUint64(a16[8:], ip.addr.lo)
675 // As4 returns an IPv4 or IPv4-in-IPv6 address in its 4-byte representation.
676 // If ip is the zero Addr or an IPv6 address, As4 panics.
677 // Note that 0.0.0.0 is not the zero Addr.
678 func (ip Addr) As4() (a4 [4]byte) {
679 if ip.z == z4 || ip.Is4In6() {
680 bePutUint32(a4[:], uint32(ip.addr.lo))
684 panic("As4 called on IP zero value")
686 panic("As4 called on IPv6 address")
689 // AsSlice returns an IPv4 or IPv6 address in its respective 4-byte or 16-byte representation.
690 func (ip Addr) AsSlice() []byte {
696 bePutUint32(ret[:], uint32(ip.addr.lo))
700 bePutUint64(ret[:8], ip.addr.hi)
701 bePutUint64(ret[8:], ip.addr.lo)
706 // Next returns the address following ip.
707 // If there is none, it returns the zero Addr.
708 func (ip Addr) Next() Addr {
709 ip.addr = ip.addr.addOne()
711 if uint32(ip.addr.lo) == 0 {
716 if ip.addr.isZero() {
724 // Prev returns the IP before ip.
725 // If there is none, it returns the IP zero value.
726 func (ip Addr) Prev() Addr {
728 if uint32(ip.addr.lo) == 0 {
731 } else if ip.addr.isZero() {
734 ip.addr = ip.addr.subOne()
738 // String returns the string form of the IP address ip.
739 // It returns one of 5 forms:
741 // - "invalid IP", if ip is the zero Addr
742 // - IPv4 dotted decimal ("192.0.2.1")
743 // - IPv6 ("2001:db8::1")
744 // - "::ffff:1.2.3.4" (if Is4In6)
745 // - IPv6 with zone ("fe80:db8::1%eth0")
747 // Note that unlike package net's IP.String method,
748 // IPv4-mapped IPv6 addresses format with a "::ffff:"
749 // prefix before the dotted quad.
750 func (ip Addr) String() string {
758 if z := ip.Zone(); z != "" {
759 return "::ffff:" + ip.Unmap().string4() + "%" + z
761 return "::ffff:" + ip.Unmap().string4()
768 // AppendTo appends a text encoding of ip,
769 // as generated by MarshalText,
770 // to b and returns the extended buffer.
771 func (ip Addr) AppendTo(b []byte) []byte {
776 return ip.appendTo4(b)
779 b = append(b, "::ffff:"...)
780 b = ip.Unmap().appendTo4(b)
781 if z := ip.Zone(); z != "" {
787 return ip.appendTo6(b)
791 // digits is a string of the hex digits from 0 to f. It's used in
792 // appendDecimal and appendHex to format IP addresses.
793 const digits = "0123456789abcdef"
795 // appendDecimal appends the decimal string representation of x to b.
796 func appendDecimal(b []byte, x uint8) []byte {
797 // Using this function rather than strconv.AppendUint makes IPv4
798 // string building 2x faster.
801 b = append(b, digits[x/100])
804 b = append(b, digits[x/10%10])
806 return append(b, digits[x%10])
809 // appendHex appends the hex string representation of x to b.
810 func appendHex(b []byte, x uint16) []byte {
811 // Using this function rather than strconv.AppendUint makes IPv6
812 // string building 2x faster.
815 b = append(b, digits[x>>12])
818 b = append(b, digits[x>>8&0xf])
821 b = append(b, digits[x>>4&0xf])
823 return append(b, digits[x&0xf])
826 // appendHexPad appends the fully padded hex string representation of x to b.
827 func appendHexPad(b []byte, x uint16) []byte {
828 return append(b, digits[x>>12], digits[x>>8&0xf], digits[x>>4&0xf], digits[x&0xf])
831 func (ip Addr) string4() string {
832 const max = len("255.255.255.255")
833 ret := make([]byte, 0, max)
834 ret = ip.appendTo4(ret)
838 func (ip Addr) appendTo4(ret []byte) []byte {
839 ret = appendDecimal(ret, ip.v4(0))
840 ret = append(ret, '.')
841 ret = appendDecimal(ret, ip.v4(1))
842 ret = append(ret, '.')
843 ret = appendDecimal(ret, ip.v4(2))
844 ret = append(ret, '.')
845 ret = appendDecimal(ret, ip.v4(3))
849 // string6 formats ip in IPv6 textual representation. It follows the
850 // guidelines in section 4 of RFC 5952
851 // (https://tools.ietf.org/html/rfc5952#section-4): no unnecessary
852 // zeros, use :: to elide the longest run of zeros, and don't use ::
853 // to compact a single zero field.
854 func (ip Addr) string6() string {
855 // Use a zone with a "plausibly long" name, so that most zone-ful
856 // IP addresses won't require additional allocation.
858 // The compiler does a cool optimization here, where ret ends up
859 // stack-allocated and so the only allocation this function does
860 // is to construct the returned string. As such, it's okay to be a
861 // bit greedy here, size-wise.
862 const max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
863 ret := make([]byte, 0, max)
864 ret = ip.appendTo6(ret)
868 func (ip Addr) appendTo6(ret []byte) []byte {
869 zeroStart, zeroEnd := uint8(255), uint8(255)
870 for i := uint8(0); i < 8; i++ {
872 for j < 8 && ip.v6u16(j) == 0 {
875 if l := j - i; l >= 2 && l > zeroEnd-zeroStart {
876 zeroStart, zeroEnd = i, j
880 for i := uint8(0); i < 8; i++ {
882 ret = append(ret, ':', ':')
888 ret = append(ret, ':')
891 ret = appendHex(ret, ip.v6u16(i))
895 ret = append(ret, '%')
896 ret = append(ret, ip.Zone()...)
901 // StringExpanded is like String but IPv6 addresses are expanded with leading
902 // zeroes and no "::" compression. For example, "2001:db8::1" becomes
903 // "2001:0db8:0000:0000:0000:0000:0000:0001".
904 func (ip Addr) StringExpanded() string {
910 const size = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
911 ret := make([]byte, 0, size)
912 for i := uint8(0); i < 8; i++ {
914 ret = append(ret, ':')
917 ret = appendHexPad(ret, ip.v6u16(i))
921 // The addition of a zone will cause a second allocation, but when there
922 // is no zone the ret slice will be stack allocated.
923 ret = append(ret, '%')
924 ret = append(ret, ip.Zone()...)
929 // MarshalText implements the encoding.TextMarshaler interface,
930 // The encoding is the same as returned by String, with one exception:
931 // If ip is the zero Addr, the encoding is the empty string.
932 func (ip Addr) MarshalText() ([]byte, error) {
935 return []byte(""), nil
937 max := len("255.255.255.255")
938 b := make([]byte, 0, max)
939 return ip.appendTo4(b), nil
941 max := len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
942 b := make([]byte, 0, max)
944 b = append(b, "::ffff:"...)
945 b = ip.Unmap().appendTo4(b)
946 if z := ip.Zone(); z != "" {
952 return ip.appendTo6(b), nil
957 // UnmarshalText implements the encoding.TextUnmarshaler interface.
958 // The IP address is expected in a form accepted by ParseAddr.
960 // If text is empty, UnmarshalText sets *ip to the zero Addr and
962 func (ip *Addr) UnmarshalText(text []byte) error {
968 *ip, err = ParseAddr(string(text))
972 func (ip Addr) marshalBinaryWithTrailingBytes(trailingBytes int) []byte {
976 b = make([]byte, trailingBytes)
978 b = make([]byte, 4+trailingBytes)
979 bePutUint32(b, uint32(ip.addr.lo))
982 b = make([]byte, 16+len(z)+trailingBytes)
983 bePutUint64(b[:8], ip.addr.hi)
984 bePutUint64(b[8:], ip.addr.lo)
990 // MarshalBinary implements the encoding.BinaryMarshaler interface.
991 // It returns a zero-length slice for the zero Addr,
992 // the 4-byte form for an IPv4 address,
993 // and the 16-byte form with zone appended for an IPv6 address.
994 func (ip Addr) MarshalBinary() ([]byte, error) {
995 return ip.marshalBinaryWithTrailingBytes(0), nil
998 // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
999 // It expects data in the form generated by MarshalBinary.
1000 func (ip *Addr) UnmarshalBinary(b []byte) error {
1007 *ip = AddrFrom4([4]byte(b))
1010 *ip = AddrFrom16([16]byte(b))
1013 *ip = AddrFrom16([16]byte(b[:16])).WithZone(string(b[16:]))
1016 return errors.New("unexpected slice size")
1019 // AddrPort is an IP and a port number.
1020 type AddrPort struct {
1025 // AddrPortFrom returns an AddrPort with the provided IP and port.
1026 // It does not allocate.
1027 func AddrPortFrom(ip Addr, port uint16) AddrPort { return AddrPort{ip: ip, port: port} }
1029 // Addr returns p's IP address.
1030 func (p AddrPort) Addr() Addr { return p.ip }
1032 // Port returns p's port.
1033 func (p AddrPort) Port() uint16 { return p.port }
1035 // splitAddrPort splits s into an IP address string and a port
1036 // string. It splits strings shaped like "foo:bar" or "[foo]:bar",
1037 // without further validating the substrings. v6 indicates whether the
1038 // ip string should parse as an IPv6 address or an IPv4 address, in
1039 // order for s to be a valid ip:port string.
1040 func splitAddrPort(s string) (ip, port string, v6 bool, err error) {
1041 i := bytealg.LastIndexByteString(s, ':')
1043 return "", "", false, errors.New("not an ip:port")
1046 ip, port = s[:i], s[i+1:]
1048 return "", "", false, errors.New("no IP")
1051 return "", "", false, errors.New("no port")
1054 if len(ip) < 2 || ip[len(ip)-1] != ']' {
1055 return "", "", false, errors.New("missing ]")
1057 ip = ip[1 : len(ip)-1]
1061 return ip, port, v6, nil
1064 // ParseAddrPort parses s as an AddrPort.
1066 // It doesn't do any name resolution: both the address and the port
1068 func ParseAddrPort(s string) (AddrPort, error) {
1070 ip, port, v6, err := splitAddrPort(s)
1074 port16, err := strconv.ParseUint(port, 10, 16)
1076 return ipp, errors.New("invalid port " + strconv.Quote(port) + " parsing " + strconv.Quote(s))
1078 ipp.port = uint16(port16)
1079 ipp.ip, err = ParseAddr(ip)
1081 return AddrPort{}, err
1083 if v6 && ipp.ip.Is4() {
1084 return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", square brackets can only be used with IPv6 addresses")
1085 } else if !v6 && ipp.ip.Is6() {
1086 return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", IPv6 addresses must be surrounded by square brackets")
1091 // MustParseAddrPort calls ParseAddrPort(s) and panics on error.
1092 // It is intended for use in tests with hard-coded strings.
1093 func MustParseAddrPort(s string) AddrPort {
1094 ip, err := ParseAddrPort(s)
1101 // IsValid reports whether p.Addr() is valid.
1102 // All ports are valid, including zero.
1103 func (p AddrPort) IsValid() bool { return p.ip.IsValid() }
1105 func (p AddrPort) String() string {
1108 return "invalid AddrPort"
1111 buf := make([]byte, 0, 21)
1113 buf = strconv.AppendUint(buf, uint64(a[i]), 10)
1114 buf = append(buf, "...:"[i])
1116 buf = strconv.AppendUint(buf, uint64(p.port), 10)
1119 // TODO: this could be more efficient allocation-wise:
1120 return joinHostPort(p.ip.String(), itoa.Itoa(int(p.port)))
1124 func joinHostPort(host, port string) string {
1125 // We assume that host is a literal IPv6 address if host has
1127 if bytealg.IndexByteString(host, ':') >= 0 {
1128 return "[" + host + "]:" + port
1130 return host + ":" + port
1133 // AppendTo appends a text encoding of p,
1134 // as generated by MarshalText,
1135 // to b and returns the extended buffer.
1136 func (p AddrPort) AppendTo(b []byte) []byte {
1141 b = p.ip.appendTo4(b)
1144 b = append(b, "[::ffff:"...)
1145 b = p.ip.Unmap().appendTo4(b)
1146 if z := p.ip.Zone(); z != "" {
1152 b = p.ip.appendTo6(b)
1157 b = strconv.AppendUint(b, uint64(p.port), 10)
1161 // MarshalText implements the encoding.TextMarshaler interface. The
1162 // encoding is the same as returned by String, with one exception: if
1163 // p.Addr() is the zero Addr, the encoding is the empty string.
1164 func (p AddrPort) MarshalText() ([]byte, error) {
1169 max = len("255.255.255.255:65535")
1171 max = len("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0]:65535")
1173 b := make([]byte, 0, max)
1178 // UnmarshalText implements the encoding.TextUnmarshaler
1179 // interface. The AddrPort is expected in a form
1180 // generated by MarshalText or accepted by ParseAddrPort.
1181 func (p *AddrPort) UnmarshalText(text []byte) error {
1187 *p, err = ParseAddrPort(string(text))
1191 // MarshalBinary implements the encoding.BinaryMarshaler interface.
1192 // It returns Addr.MarshalBinary with an additional two bytes appended
1193 // containing the port in little-endian.
1194 func (p AddrPort) MarshalBinary() ([]byte, error) {
1195 b := p.Addr().marshalBinaryWithTrailingBytes(2)
1196 lePutUint16(b[len(b)-2:], p.Port())
1200 // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
1201 // It expects data in the form generated by MarshalBinary.
1202 func (p *AddrPort) UnmarshalBinary(b []byte) error {
1204 return errors.New("unexpected slice size")
1207 err := addr.UnmarshalBinary(b[:len(b)-2])
1211 *p = AddrPortFrom(addr, leUint16(b[len(b)-2:]))
1215 // Prefix is an IP address prefix (CIDR) representing an IP network.
1217 // The first Bits() of Addr() are specified. The remaining bits match any address.
1218 // The range of Bits() is [0,32] for IPv4 or [0,128] for IPv6.
1219 type Prefix struct {
1222 // bitsPlusOne stores the prefix bit length plus one.
1223 // A Prefix is valid if and only if bitsPlusOne is non-zero.
1227 // PrefixFrom returns a Prefix with the provided IP address and bit
1230 // It does not allocate. Unlike Addr.Prefix, PrefixFrom does not mask
1231 // off the host bits of ip.
1233 // If bits is less than zero or greater than ip.BitLen, Prefix.Bits
1234 // will return an invalid value -1.
1235 func PrefixFrom(ip Addr, bits int) Prefix {
1236 var bitsPlusOne uint8
1237 if !ip.isZero() && bits >= 0 && bits <= ip.BitLen() {
1238 bitsPlusOne = uint8(bits) + 1
1241 ip: ip.withoutZone(),
1242 bitsPlusOne: bitsPlusOne,
1246 // Addr returns p's IP address.
1247 func (p Prefix) Addr() Addr { return p.ip }
1249 // Bits returns p's prefix length.
1251 // It reports -1 if invalid.
1252 func (p Prefix) Bits() int { return int(p.bitsPlusOne) - 1 }
1254 // IsValid reports whether p.Bits() has a valid range for p.Addr().
1255 // If p.Addr() is the zero Addr, IsValid returns false.
1256 // Note that if p is the zero Prefix, then p.IsValid() == false.
1257 func (p Prefix) IsValid() bool { return p.bitsPlusOne > 0 }
1259 func (p Prefix) isZero() bool { return p == Prefix{} }
1261 // IsSingleIP reports whether p contains exactly one IP.
1262 func (p Prefix) IsSingleIP() bool { return p.IsValid() && p.Bits() == p.ip.BitLen() }
1264 // ParsePrefix parses s as an IP address prefix.
1265 // The string can be in the form "192.168.1.0/24" or "2001:db8::/32",
1266 // the CIDR notation defined in RFC 4632 and RFC 4291.
1267 // IPv6 zones are not permitted in prefixes, and an error will be returned if a
1270 // Note that masked address bits are not zeroed. Use Masked for that.
1271 func ParsePrefix(s string) (Prefix, error) {
1272 i := bytealg.LastIndexByteString(s, '/')
1274 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): no '/'")
1276 ip, err := ParseAddr(s[:i])
1278 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): " + err.Error())
1280 // IPv6 zones are not allowed: https://go.dev/issue/51899
1281 if ip.Is6() && ip.z != z6noz {
1282 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): IPv6 zones cannot be present in a prefix")
1286 bits, err := strconv.Atoi(bitsStr)
1288 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): bad bits after slash: " + strconv.Quote(bitsStr))
1294 if bits < 0 || bits > maxBits {
1295 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): prefix length out of range")
1297 return PrefixFrom(ip, bits), nil
1300 // MustParsePrefix calls ParsePrefix(s) and panics on error.
1301 // It is intended for use in tests with hard-coded strings.
1302 func MustParsePrefix(s string) Prefix {
1303 ip, err := ParsePrefix(s)
1310 // Masked returns p in its canonical form, with all but the high
1311 // p.Bits() bits of p.Addr() masked off.
1313 // If p is zero or otherwise invalid, Masked returns the zero Prefix.
1314 func (p Prefix) Masked() Prefix {
1315 m, _ := p.ip.Prefix(p.Bits())
1319 // Contains reports whether the network p includes ip.
1321 // An IPv4 address will not match an IPv6 prefix.
1322 // An IPv4-mapped IPv6 address will not match an IPv4 prefix.
1323 // A zero-value IP will not match any prefix.
1324 // If ip has an IPv6 zone, Contains returns false,
1325 // because Prefixes strip zones.
1326 func (p Prefix) Contains(ip Addr) bool {
1327 if !p.IsValid() || ip.hasZone() {
1330 if f1, f2 := p.ip.BitLen(), ip.BitLen(); f1 == 0 || f2 == 0 || f1 != f2 {
1334 // xor the IP addresses together; mismatched bits are now ones.
1335 // Shift away the number of bits we don't care about.
1336 // Shifts in Go are more efficient if the compiler can prove
1337 // that the shift amount is smaller than the width of the shifted type (64 here).
1338 // We know that p.bits is in the range 0..32 because p is Valid;
1339 // the compiler doesn't know that, so mask with 63 to help it.
1340 // Now truncate to 32 bits, because this is IPv4.
1341 // If all the bits we care about are equal, the result will be zero.
1342 return uint32((ip.addr.lo^p.ip.addr.lo)>>((32-p.Bits())&63)) == 0
1344 // xor the IP addresses together.
1345 // Mask away the bits we don't care about.
1346 // If all the bits we care about are equal, the result will be zero.
1347 return ip.addr.xor(p.ip.addr).and(mask6(p.Bits())).isZero()
1351 // Overlaps reports whether p and o contain any IP addresses in common.
1353 // If p and o are of different address families or either have a zero
1354 // IP, it reports false. Like the Contains method, a prefix with an
1355 // IPv4-mapped IPv6 address is still treated as an IPv6 mask.
1356 func (p Prefix) Overlaps(o Prefix) bool {
1357 if !p.IsValid() || !o.IsValid() {
1363 if p.ip.Is4() != o.ip.Is4() {
1367 if pb, ob := p.Bits(), o.Bits(); pb < ob {
1375 // One of these Prefix calls might look redundant, but we don't require
1376 // that p and o values are normalized (via Prefix.Masked) first,
1377 // so the Prefix call on the one that's already minBits serves to zero
1378 // out any remaining bits in IP.
1380 if p, err = p.ip.Prefix(minBits); err != nil {
1383 if o, err = o.ip.Prefix(minBits); err != nil {
1389 // AppendTo appends a text encoding of p,
1390 // as generated by MarshalText,
1391 // to b and returns the extended buffer.
1392 func (p Prefix) AppendTo(b []byte) []byte {
1397 return append(b, "invalid Prefix"...)
1400 // p.ip is non-nil, because p is valid.
1402 b = p.ip.appendTo4(b)
1405 b = append(b, "::ffff:"...)
1406 b = p.ip.Unmap().appendTo4(b)
1408 b = p.ip.appendTo6(b)
1413 b = appendDecimal(b, uint8(p.Bits()))
1417 // MarshalText implements the encoding.TextMarshaler interface,
1418 // The encoding is the same as returned by String, with one exception:
1419 // If p is the zero value, the encoding is the empty string.
1420 func (p Prefix) MarshalText() ([]byte, error) {
1425 max = len("255.255.255.255/32")
1427 max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0/128")
1429 b := make([]byte, 0, max)
1434 // UnmarshalText implements the encoding.TextUnmarshaler interface.
1435 // The IP address is expected in a form accepted by ParsePrefix
1436 // or generated by MarshalText.
1437 func (p *Prefix) UnmarshalText(text []byte) error {
1443 *p, err = ParsePrefix(string(text))
1447 // MarshalBinary implements the encoding.BinaryMarshaler interface.
1448 // It returns Addr.MarshalBinary with an additional byte appended
1449 // containing the prefix bits.
1450 func (p Prefix) MarshalBinary() ([]byte, error) {
1451 b := p.Addr().withoutZone().marshalBinaryWithTrailingBytes(1)
1452 b[len(b)-1] = uint8(p.Bits())
1456 // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
1457 // It expects data in the form generated by MarshalBinary.
1458 func (p *Prefix) UnmarshalBinary(b []byte) error {
1460 return errors.New("unexpected slice size")
1463 err := addr.UnmarshalBinary(b[:len(b)-1])
1467 *p = PrefixFrom(addr, int(b[len(b)-1]))
1471 // String returns the CIDR notation of p: "<ip>/<bits>".
1472 func (p Prefix) String() string {
1474 return "invalid Prefix"
1476 return p.ip.String() + "/" + itoa.Itoa(p.Bits())