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