Source file
src/net/netip/netip.go
1
2
3
4
5
6
7
8
9
10
11
12 package netip
13
14 import (
15 "cmp"
16 "errors"
17 "math"
18 "strconv"
19
20 "internal/bytealg"
21 "internal/intern"
22 "internal/itoa"
23 )
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 type Addr struct {
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 addr uint128
55
56
57
58
59
60
61
62
63 z *intern.Value
64 }
65
66
67
68 var (
69 z0 = (*intern.Value)(nil)
70 z4 = new(intern.Value)
71 z6noz = new(intern.Value)
72 )
73
74
75
76 func IPv6LinkLocalAllNodes() Addr { return AddrFrom16([16]byte{0: 0xff, 1: 0x02, 15: 0x01}) }
77
78
79
80 func IPv6LinkLocalAllRouters() Addr { return AddrFrom16([16]byte{0: 0xff, 1: 0x02, 15: 0x02}) }
81
82
83 func IPv6Loopback() Addr { return AddrFrom16([16]byte{15: 0x01}) }
84
85
86 func IPv6Unspecified() Addr { return Addr{z: z6noz} }
87
88
89 func IPv4Unspecified() Addr { return AddrFrom4([4]byte{}) }
90
91
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
100
101
102 func AddrFrom16(addr [16]byte) Addr {
103 return Addr{
104 addr: uint128{
105 beUint64(addr[:8]),
106 beUint64(addr[8:]),
107 },
108 z: z6noz,
109 }
110 }
111
112
113
114
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
124
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
132
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
143 msg string
144 at string
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
156 func parseIPv4(s string) (ip Addr, err error) {
157 var fields [4]uint8
158 var val, pos int
159 var digLen int
160 for i := 0; i < len(s); i++ {
161 if s[i] >= '0' && s[i] <= '9' {
162 if digLen == 1 && val == 0 {
163 return Addr{}, parseAddrError{in: s, msg: "IPv4 field has octet with leading zero"}
164 }
165 val = val*10 + int(s[i]) - '0'
166 digLen++
167 if val > 255 {
168 return Addr{}, parseAddrError{in: s, msg: "IPv4 field has value >255"}
169 }
170 } else if s[i] == '.' {
171
172
173
174 if i == 0 || i == len(s)-1 || s[i-1] == '.' {
175 return Addr{}, parseAddrError{in: s, msg: "IPv4 field must have at least one digit", at: s[i:]}
176 }
177
178 if pos == 3 {
179 return Addr{}, parseAddrError{in: s, msg: "IPv4 address too long"}
180 }
181 fields[pos] = uint8(val)
182 pos++
183 val = 0
184 digLen = 0
185 } else {
186 return Addr{}, parseAddrError{in: s, msg: "unexpected character", at: s[i:]}
187 }
188 }
189 if pos < 3 {
190 return Addr{}, parseAddrError{in: s, msg: "IPv4 address too short"}
191 }
192 fields[3] = uint8(val)
193 return AddrFrom4(fields), nil
194 }
195
196
197 func parseIPv6(in string) (Addr, error) {
198 s := in
199
200
201
202
203
204 zone := ""
205 i := bytealg.IndexByteString(s, '%')
206 if i != -1 {
207 s, zone = s[:i], s[i+1:]
208 if zone == "" {
209
210 return Addr{}, parseAddrError{in: in, msg: "zone must be a non-empty string"}
211 }
212 }
213
214 var ip [16]byte
215 ellipsis := -1
216
217
218 if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
219 ellipsis = 0
220 s = s[2:]
221
222 if len(s) == 0 {
223 return IPv6Unspecified().WithZone(zone), nil
224 }
225 }
226
227
228 i = 0
229 for i < 16 {
230
231
232 off := 0
233 acc := uint32(0)
234 for ; off < len(s); off++ {
235 c := s[off]
236 if c >= '0' && c <= '9' {
237 acc = (acc << 4) + uint32(c-'0')
238 } else if c >= 'a' && c <= 'f' {
239 acc = (acc << 4) + uint32(c-'a'+10)
240 } else if c >= 'A' && c <= 'F' {
241 acc = (acc << 4) + uint32(c-'A'+10)
242 } else {
243 break
244 }
245 if acc > math.MaxUint16 {
246
247 return Addr{}, parseAddrError{in: in, msg: "IPv6 field has value >=2^16", at: s}
248 }
249 }
250 if off == 0 {
251
252 return Addr{}, parseAddrError{in: in, msg: "each colon-separated field must have at least one digit", at: s}
253 }
254
255
256 if off < len(s) && s[off] == '.' {
257 if ellipsis < 0 && i != 12 {
258
259 return Addr{}, parseAddrError{in: in, msg: "embedded IPv4 address must replace the final 2 fields of the address", at: s}
260 }
261 if i+4 > 16 {
262
263 return Addr{}, parseAddrError{in: in, msg: "too many hex fields to fit an embedded IPv4 at the end of the address", at: s}
264 }
265
266
267
268 ip4, err := parseIPv4(s)
269 if err != nil {
270 return Addr{}, parseAddrError{in: in, msg: err.Error(), at: s}
271 }
272 ip[i] = ip4.v4(0)
273 ip[i+1] = ip4.v4(1)
274 ip[i+2] = ip4.v4(2)
275 ip[i+3] = ip4.v4(3)
276 s = ""
277 i += 4
278 break
279 }
280
281
282 ip[i] = byte(acc >> 8)
283 ip[i+1] = byte(acc)
284 i += 2
285
286
287 s = s[off:]
288 if len(s) == 0 {
289 break
290 }
291
292
293 if s[0] != ':' {
294 return Addr{}, parseAddrError{in: in, msg: "unexpected character, want colon", at: s}
295 } else if len(s) == 1 {
296 return Addr{}, parseAddrError{in: in, msg: "colon must be followed by more characters", at: s}
297 }
298 s = s[1:]
299
300
301 if s[0] == ':' {
302 if ellipsis >= 0 {
303 return Addr{}, parseAddrError{in: in, msg: "multiple :: in address", at: s}
304 }
305 ellipsis = i
306 s = s[1:]
307 if len(s) == 0 {
308 break
309 }
310 }
311 }
312
313
314 if len(s) != 0 {
315 return Addr{}, parseAddrError{in: in, msg: "trailing garbage after address", at: s}
316 }
317
318
319 if i < 16 {
320 if ellipsis < 0 {
321 return Addr{}, parseAddrError{in: in, msg: "address string too short"}
322 }
323 n := 16 - i
324 for j := i - 1; j >= ellipsis; j-- {
325 ip[j+n] = ip[j]
326 }
327 for j := ellipsis + n - 1; j >= ellipsis; j-- {
328 ip[j] = 0
329 }
330 } else if ellipsis >= 0 {
331
332 return Addr{}, parseAddrError{in: in, msg: "the :: must expand to at least one field of zeros"}
333 }
334 return AddrFrom16(ip).WithZone(zone), nil
335 }
336
337
338
339
340 func AddrFromSlice(slice []byte) (ip Addr, ok bool) {
341 switch len(slice) {
342 case 4:
343 return AddrFrom4([4]byte(slice)), true
344 case 16:
345 return AddrFrom16([16]byte(slice)), true
346 }
347 return Addr{}, false
348 }
349
350
351
352 func (ip Addr) v4(i uint8) uint8 {
353 return uint8(ip.addr.lo >> ((3 - i) * 8))
354 }
355
356
357
358 func (ip Addr) v6(i uint8) uint8 {
359 return uint8(*(ip.addr.halves()[(i/8)%2]) >> ((7 - i%8) * 8))
360 }
361
362
363
364 func (ip Addr) v6u16(i uint8) uint16 {
365 return uint16(*(ip.addr.halves()[(i/4)%2]) >> ((3 - i%4) * 16))
366 }
367
368
369
370
371
372
373 func (ip Addr) isZero() bool {
374
375
376 return ip.z == z0
377 }
378
379
380
381
382 func (ip Addr) IsValid() bool { return ip.z != z0 }
383
384
385
386
387
388
389 func (ip Addr) BitLen() int {
390 switch ip.z {
391 case z0:
392 return 0
393 case z4:
394 return 32
395 }
396 return 128
397 }
398
399
400 func (ip Addr) Zone() string {
401 if ip.z == nil {
402 return ""
403 }
404 zone, _ := ip.z.Get().(string)
405 return zone
406 }
407
408
409
410
411 func (ip Addr) Compare(ip2 Addr) int {
412 f1, f2 := ip.BitLen(), ip2.BitLen()
413 if f1 < f2 {
414 return -1
415 }
416 if f1 > f2 {
417 return 1
418 }
419 hi1, hi2 := ip.addr.hi, ip2.addr.hi
420 if hi1 < hi2 {
421 return -1
422 }
423 if hi1 > hi2 {
424 return 1
425 }
426 lo1, lo2 := ip.addr.lo, ip2.addr.lo
427 if lo1 < lo2 {
428 return -1
429 }
430 if lo1 > lo2 {
431 return 1
432 }
433 if ip.Is6() {
434 za, zb := ip.Zone(), ip2.Zone()
435 if za < zb {
436 return -1
437 }
438 if za > zb {
439 return 1
440 }
441 }
442 return 0
443 }
444
445
446
447
448 func (ip Addr) Less(ip2 Addr) bool { return ip.Compare(ip2) == -1 }
449
450
451
452
453 func (ip Addr) Is4() bool {
454 return ip.z == z4
455 }
456
457
458 func (ip Addr) Is4In6() bool {
459 return ip.Is6() && ip.addr.hi == 0 && ip.addr.lo>>32 == 0xffff
460 }
461
462
463
464 func (ip Addr) Is6() bool {
465 return ip.z != z0 && ip.z != z4
466 }
467
468
469
470
471
472 func (ip Addr) Unmap() Addr {
473 if ip.Is4In6() {
474 ip.z = z4
475 }
476 return ip
477 }
478
479
480
481
482 func (ip Addr) WithZone(zone string) Addr {
483 if !ip.Is6() {
484 return ip
485 }
486 if zone == "" {
487 ip.z = z6noz
488 return ip
489 }
490 ip.z = intern.GetByString(zone)
491 return ip
492 }
493
494
495
496 func (ip Addr) withoutZone() Addr {
497 if !ip.Is6() {
498 return ip
499 }
500 ip.z = z6noz
501 return ip
502 }
503
504
505 func (ip Addr) hasZone() bool {
506 return ip.z != z0 && ip.z != z4 && ip.z != z6noz
507 }
508
509
510 func (ip Addr) IsLinkLocalUnicast() bool {
511
512
513 if ip.Is4() {
514 return ip.v4(0) == 169 && ip.v4(1) == 254
515 }
516
517
518 if ip.Is6() {
519 return ip.v6u16(0)&0xffc0 == 0xfe80
520 }
521 return false
522 }
523
524
525 func (ip Addr) IsLoopback() bool {
526
527
528 if ip.Is4() {
529 return ip.v4(0) == 127
530 }
531
532
533 if ip.Is6() {
534 return ip.addr.hi == 0 && ip.addr.lo == 1
535 }
536 return false
537 }
538
539
540 func (ip Addr) IsMulticast() bool {
541
542
543 if ip.Is4() {
544 return ip.v4(0)&0xf0 == 0xe0
545 }
546
547
548 if ip.Is6() {
549 return ip.addr.hi>>(64-8) == 0xff
550 }
551 return false
552 }
553
554
555
556 func (ip Addr) IsInterfaceLocalMulticast() bool {
557
558
559 if ip.Is6() {
560 return ip.v6u16(0)&0xff0f == 0xff01
561 }
562 return false
563 }
564
565
566 func (ip Addr) IsLinkLocalMulticast() bool {
567
568
569 if ip.Is4() {
570 return ip.v4(0) == 224 && ip.v4(1) == 0 && ip.v4(2) == 0
571 }
572
573
574 if ip.Is6() {
575 return ip.v6u16(0)&0xff0f == 0xff02
576 }
577 return false
578 }
579
580
581
582
583
584
585
586
587
588
589 func (ip Addr) IsGlobalUnicast() bool {
590 if ip.z == z0 {
591
592 return false
593 }
594
595
596
597 if ip.Is4() && (ip == IPv4Unspecified() || ip == AddrFrom4([4]byte{255, 255, 255, 255})) {
598 return false
599 }
600
601 return ip != IPv6Unspecified() &&
602 !ip.IsLoopback() &&
603 !ip.IsMulticast() &&
604 !ip.IsLinkLocalUnicast()
605 }
606
607
608
609
610
611 func (ip Addr) IsPrivate() bool {
612
613 if ip.Is4() {
614
615
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)
619 }
620
621 if ip.Is6() {
622
623
624 return ip.v6(0)&0xfe == 0xfc
625 }
626
627 return false
628 }
629
630
631
632
633
634 func (ip Addr) IsUnspecified() bool {
635 return ip == IPv4Unspecified() || ip == IPv6Unspecified()
636 }
637
638
639
640
641
642
643 func (ip Addr) Prefix(b int) (Prefix, error) {
644 if b < 0 {
645 return Prefix{}, errors.New("negative Prefix bits")
646 }
647 effectiveBits := b
648 switch ip.z {
649 case z0:
650 return Prefix{}, nil
651 case z4:
652 if b > 32 {
653 return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv4")
654 }
655 effectiveBits += 96
656 default:
657 if b > 128 {
658 return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv6")
659 }
660 }
661 ip.addr = ip.addr.and(mask6(effectiveBits))
662 return PrefixFrom(ip, b), nil
663 }
664
665
666
667
668
669
670 func (ip Addr) As16() (a16 [16]byte) {
671 bePutUint64(a16[:8], ip.addr.hi)
672 bePutUint64(a16[8:], ip.addr.lo)
673 return a16
674 }
675
676
677
678
679 func (ip Addr) As4() (a4 [4]byte) {
680 if ip.z == z4 || ip.Is4In6() {
681 bePutUint32(a4[:], uint32(ip.addr.lo))
682 return a4
683 }
684 if ip.z == z0 {
685 panic("As4 called on IP zero value")
686 }
687 panic("As4 called on IPv6 address")
688 }
689
690
691 func (ip Addr) AsSlice() []byte {
692 switch ip.z {
693 case z0:
694 return nil
695 case z4:
696 var ret [4]byte
697 bePutUint32(ret[:], uint32(ip.addr.lo))
698 return ret[:]
699 default:
700 var ret [16]byte
701 bePutUint64(ret[:8], ip.addr.hi)
702 bePutUint64(ret[8:], ip.addr.lo)
703 return ret[:]
704 }
705 }
706
707
708
709 func (ip Addr) Next() Addr {
710 ip.addr = ip.addr.addOne()
711 if ip.Is4() {
712 if uint32(ip.addr.lo) == 0 {
713
714 return Addr{}
715 }
716 } else {
717 if ip.addr.isZero() {
718
719 return Addr{}
720 }
721 }
722 return ip
723 }
724
725
726
727 func (ip Addr) Prev() Addr {
728 if ip.Is4() {
729 if uint32(ip.addr.lo) == 0 {
730 return Addr{}
731 }
732 } else if ip.addr.isZero() {
733 return Addr{}
734 }
735 ip.addr = ip.addr.subOne()
736 return ip
737 }
738
739
740
741
742
743
744
745
746
747
748
749
750
751 func (ip Addr) String() string {
752 switch ip.z {
753 case z0:
754 return "invalid IP"
755 case z4:
756 return ip.string4()
757 default:
758 if ip.Is4In6() {
759 if z := ip.Zone(); z != "" {
760 return "::ffff:" + ip.Unmap().string4() + "%" + z
761 } else {
762 return "::ffff:" + ip.Unmap().string4()
763 }
764 }
765 return ip.string6()
766 }
767 }
768
769
770
771
772 func (ip Addr) AppendTo(b []byte) []byte {
773 switch ip.z {
774 case z0:
775 return b
776 case z4:
777 return ip.appendTo4(b)
778 default:
779 if ip.Is4In6() {
780 b = append(b, "::ffff:"...)
781 b = ip.Unmap().appendTo4(b)
782 if z := ip.Zone(); z != "" {
783 b = append(b, '%')
784 b = append(b, z...)
785 }
786 return b
787 }
788 return ip.appendTo6(b)
789 }
790 }
791
792
793
794 const digits = "0123456789abcdef"
795
796
797 func appendDecimal(b []byte, x uint8) []byte {
798
799
800
801 if x >= 100 {
802 b = append(b, digits[x/100])
803 }
804 if x >= 10 {
805 b = append(b, digits[x/10%10])
806 }
807 return append(b, digits[x%10])
808 }
809
810
811 func appendHex(b []byte, x uint16) []byte {
812
813
814
815 if x >= 0x1000 {
816 b = append(b, digits[x>>12])
817 }
818 if x >= 0x100 {
819 b = append(b, digits[x>>8&0xf])
820 }
821 if x >= 0x10 {
822 b = append(b, digits[x>>4&0xf])
823 }
824 return append(b, digits[x&0xf])
825 }
826
827
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])
830 }
831
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)
836 return string(ret)
837 }
838
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))
847 return ret
848 }
849
850
851
852
853
854
855 func (ip Addr) string6() string {
856
857
858
859
860
861
862
863 const max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
864 ret := make([]byte, 0, max)
865 ret = ip.appendTo6(ret)
866 return string(ret)
867 }
868
869 func (ip Addr) appendTo6(ret []byte) []byte {
870 zeroStart, zeroEnd := uint8(255), uint8(255)
871 for i := uint8(0); i < 8; i++ {
872 j := i
873 for j < 8 && ip.v6u16(j) == 0 {
874 j++
875 }
876 if l := j - i; l >= 2 && l > zeroEnd-zeroStart {
877 zeroStart, zeroEnd = i, j
878 }
879 }
880
881 for i := uint8(0); i < 8; i++ {
882 if i == zeroStart {
883 ret = append(ret, ':', ':')
884 i = zeroEnd
885 if i >= 8 {
886 break
887 }
888 } else if i > 0 {
889 ret = append(ret, ':')
890 }
891
892 ret = appendHex(ret, ip.v6u16(i))
893 }
894
895 if ip.z != z6noz {
896 ret = append(ret, '%')
897 ret = append(ret, ip.Zone()...)
898 }
899 return ret
900 }
901
902
903
904
905 func (ip Addr) StringExpanded() string {
906 switch ip.z {
907 case z0, z4:
908 return ip.String()
909 }
910
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++ {
914 if i > 0 {
915 ret = append(ret, ':')
916 }
917
918 ret = appendHexPad(ret, ip.v6u16(i))
919 }
920
921 if ip.z != z6noz {
922
923
924 ret = append(ret, '%')
925 ret = append(ret, ip.Zone()...)
926 }
927 return string(ret)
928 }
929
930
931
932
933 func (ip Addr) MarshalText() ([]byte, error) {
934 switch ip.z {
935 case z0:
936 return []byte(""), nil
937 case z4:
938 max := len("255.255.255.255")
939 b := make([]byte, 0, max)
940 return ip.appendTo4(b), nil
941 default:
942 max := len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
943 b := make([]byte, 0, max)
944 if ip.Is4In6() {
945 b = append(b, "::ffff:"...)
946 b = ip.Unmap().appendTo4(b)
947 if z := ip.Zone(); z != "" {
948 b = append(b, '%')
949 b = append(b, z...)
950 }
951 return b, nil
952 }
953 return ip.appendTo6(b), nil
954 }
955
956 }
957
958
959
960
961
962
963 func (ip *Addr) UnmarshalText(text []byte) error {
964 if len(text) == 0 {
965 *ip = Addr{}
966 return nil
967 }
968 var err error
969 *ip, err = ParseAddr(string(text))
970 return err
971 }
972
973 func (ip Addr) marshalBinaryWithTrailingBytes(trailingBytes int) []byte {
974 var b []byte
975 switch ip.z {
976 case z0:
977 b = make([]byte, trailingBytes)
978 case z4:
979 b = make([]byte, 4+trailingBytes)
980 bePutUint32(b, uint32(ip.addr.lo))
981 default:
982 z := ip.Zone()
983 b = make([]byte, 16+len(z)+trailingBytes)
984 bePutUint64(b[:8], ip.addr.hi)
985 bePutUint64(b[8:], ip.addr.lo)
986 copy(b[16:], z)
987 }
988 return b
989 }
990
991
992
993
994
995 func (ip Addr) MarshalBinary() ([]byte, error) {
996 return ip.marshalBinaryWithTrailingBytes(0), nil
997 }
998
999
1000
1001 func (ip *Addr) UnmarshalBinary(b []byte) error {
1002 n := len(b)
1003 switch {
1004 case n == 0:
1005 *ip = Addr{}
1006 return nil
1007 case n == 4:
1008 *ip = AddrFrom4([4]byte(b))
1009 return nil
1010 case n == 16:
1011 *ip = AddrFrom16([16]byte(b))
1012 return nil
1013 case n > 16:
1014 *ip = AddrFrom16([16]byte(b[:16])).WithZone(string(b[16:]))
1015 return nil
1016 }
1017 return errors.New("unexpected slice size")
1018 }
1019
1020
1021 type AddrPort struct {
1022 ip Addr
1023 port uint16
1024 }
1025
1026
1027
1028 func AddrPortFrom(ip Addr, port uint16) AddrPort { return AddrPort{ip: ip, port: port} }
1029
1030
1031 func (p AddrPort) Addr() Addr { return p.ip }
1032
1033
1034 func (p AddrPort) Port() uint16 { return p.port }
1035
1036
1037
1038
1039
1040
1041 func splitAddrPort(s string) (ip, port string, v6 bool, err error) {
1042 i := bytealg.LastIndexByteString(s, ':')
1043 if i == -1 {
1044 return "", "", false, errors.New("not an ip:port")
1045 }
1046
1047 ip, port = s[:i], s[i+1:]
1048 if len(ip) == 0 {
1049 return "", "", false, errors.New("no IP")
1050 }
1051 if len(port) == 0 {
1052 return "", "", false, errors.New("no port")
1053 }
1054 if ip[0] == '[' {
1055 if len(ip) < 2 || ip[len(ip)-1] != ']' {
1056 return "", "", false, errors.New("missing ]")
1057 }
1058 ip = ip[1 : len(ip)-1]
1059 v6 = true
1060 }
1061
1062 return ip, port, v6, nil
1063 }
1064
1065
1066
1067
1068
1069 func ParseAddrPort(s string) (AddrPort, error) {
1070 var ipp AddrPort
1071 ip, port, v6, err := splitAddrPort(s)
1072 if err != nil {
1073 return ipp, err
1074 }
1075 port16, err := strconv.ParseUint(port, 10, 16)
1076 if err != nil {
1077 return ipp, errors.New("invalid port " + strconv.Quote(port) + " parsing " + strconv.Quote(s))
1078 }
1079 ipp.port = uint16(port16)
1080 ipp.ip, err = ParseAddr(ip)
1081 if err != nil {
1082 return AddrPort{}, err
1083 }
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")
1088 }
1089 return ipp, nil
1090 }
1091
1092
1093
1094 func MustParseAddrPort(s string) AddrPort {
1095 ip, err := ParseAddrPort(s)
1096 if err != nil {
1097 panic(err)
1098 }
1099 return ip
1100 }
1101
1102
1103
1104 func (p AddrPort) IsValid() bool { return p.ip.IsValid() }
1105
1106
1107
1108
1109 func (p AddrPort) Compare(p2 AddrPort) int {
1110 if c := p.Addr().Compare(p2.Addr()); c != 0 {
1111 return c
1112 }
1113 return cmp.Compare(p.Port(), p2.Port())
1114 }
1115
1116 func (p AddrPort) String() string {
1117 switch p.ip.z {
1118 case z0:
1119 return "invalid AddrPort"
1120 case z4:
1121 const max = len("255.255.255.255:65535")
1122 buf := make([]byte, 0, max)
1123 buf = p.ip.appendTo4(buf)
1124 buf = append(buf, ':')
1125 buf = strconv.AppendUint(buf, uint64(p.port), 10)
1126 return string(buf)
1127 default:
1128
1129 return "[" + p.ip.String() + "]:" + itoa.Uitoa(uint(p.port))
1130 }
1131 }
1132
1133
1134
1135
1136 func (p AddrPort) AppendTo(b []byte) []byte {
1137 switch p.ip.z {
1138 case z0:
1139 return b
1140 case z4:
1141 b = p.ip.appendTo4(b)
1142 default:
1143 if p.ip.Is4In6() {
1144 b = append(b, "[::ffff:"...)
1145 b = p.ip.Unmap().appendTo4(b)
1146 if z := p.ip.Zone(); z != "" {
1147 b = append(b, '%')
1148 b = append(b, z...)
1149 }
1150 } else {
1151 b = append(b, '[')
1152 b = p.ip.appendTo6(b)
1153 }
1154 b = append(b, ']')
1155 }
1156 b = append(b, ':')
1157 b = strconv.AppendUint(b, uint64(p.port), 10)
1158 return b
1159 }
1160
1161
1162
1163
1164 func (p AddrPort) MarshalText() ([]byte, error) {
1165 var max int
1166 switch p.ip.z {
1167 case z0:
1168 case z4:
1169 max = len("255.255.255.255:65535")
1170 default:
1171 max = len("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0]:65535")
1172 }
1173 b := make([]byte, 0, max)
1174 b = p.AppendTo(b)
1175 return b, nil
1176 }
1177
1178
1179
1180
1181 func (p *AddrPort) UnmarshalText(text []byte) error {
1182 if len(text) == 0 {
1183 *p = AddrPort{}
1184 return nil
1185 }
1186 var err error
1187 *p, err = ParseAddrPort(string(text))
1188 return err
1189 }
1190
1191
1192
1193
1194 func (p AddrPort) MarshalBinary() ([]byte, error) {
1195 b := p.Addr().marshalBinaryWithTrailingBytes(2)
1196 lePutUint16(b[len(b)-2:], p.Port())
1197 return b, nil
1198 }
1199
1200
1201
1202 func (p *AddrPort) UnmarshalBinary(b []byte) error {
1203 if len(b) < 2 {
1204 return errors.New("unexpected slice size")
1205 }
1206 var addr Addr
1207 err := addr.UnmarshalBinary(b[:len(b)-2])
1208 if err != nil {
1209 return err
1210 }
1211 *p = AddrPortFrom(addr, leUint16(b[len(b)-2:]))
1212 return nil
1213 }
1214
1215
1216
1217
1218
1219 type Prefix struct {
1220 ip Addr
1221
1222
1223
1224 bitsPlusOne uint8
1225 }
1226
1227
1228
1229
1230
1231
1232
1233
1234
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
1239 }
1240 return Prefix{
1241 ip: ip.withoutZone(),
1242 bitsPlusOne: bitsPlusOne,
1243 }
1244 }
1245
1246
1247 func (p Prefix) Addr() Addr { return p.ip }
1248
1249
1250
1251
1252 func (p Prefix) Bits() int { return int(p.bitsPlusOne) - 1 }
1253
1254
1255
1256
1257 func (p Prefix) IsValid() bool { return p.bitsPlusOne > 0 }
1258
1259 func (p Prefix) isZero() bool { return p == Prefix{} }
1260
1261
1262 func (p Prefix) IsSingleIP() bool { return p.IsValid() && p.Bits() == p.ip.BitLen() }
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272 func (p Prefix) compare(p2 Prefix) int {
1273 if c := cmp.Compare(p.Addr().BitLen(), p2.Addr().BitLen()); c != 0 {
1274 return c
1275 }
1276 if c := cmp.Compare(p.Bits(), p2.Bits()); c != 0 {
1277 return c
1278 }
1279 return p.Addr().Compare(p2.Addr())
1280 }
1281
1282
1283
1284
1285
1286
1287
1288
1289 func ParsePrefix(s string) (Prefix, error) {
1290 i := bytealg.LastIndexByteString(s, '/')
1291 if i < 0 {
1292 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): no '/'")
1293 }
1294 ip, err := ParseAddr(s[:i])
1295 if err != nil {
1296 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): " + err.Error())
1297 }
1298
1299 if ip.Is6() && ip.z != z6noz {
1300 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): IPv6 zones cannot be present in a prefix")
1301 }
1302
1303 bitsStr := s[i+1:]
1304
1305
1306 if len(bitsStr) > 1 && (bitsStr[0] < '1' || bitsStr[0] > '9') {
1307 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): bad bits after slash: " + strconv.Quote(bitsStr))
1308 }
1309
1310 bits, err := strconv.Atoi(bitsStr)
1311 if err != nil {
1312 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): bad bits after slash: " + strconv.Quote(bitsStr))
1313 }
1314 maxBits := 32
1315 if ip.Is6() {
1316 maxBits = 128
1317 }
1318 if bits < 0 || bits > maxBits {
1319 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): prefix length out of range")
1320 }
1321 return PrefixFrom(ip, bits), nil
1322 }
1323
1324
1325
1326 func MustParsePrefix(s string) Prefix {
1327 ip, err := ParsePrefix(s)
1328 if err != nil {
1329 panic(err)
1330 }
1331 return ip
1332 }
1333
1334
1335
1336
1337
1338 func (p Prefix) Masked() Prefix {
1339 m, _ := p.ip.Prefix(p.Bits())
1340 return m
1341 }
1342
1343
1344
1345
1346
1347
1348
1349
1350 func (p Prefix) Contains(ip Addr) bool {
1351 if !p.IsValid() || ip.hasZone() {
1352 return false
1353 }
1354 if f1, f2 := p.ip.BitLen(), ip.BitLen(); f1 == 0 || f2 == 0 || f1 != f2 {
1355 return false
1356 }
1357 if ip.Is4() {
1358
1359
1360
1361
1362
1363
1364
1365
1366 return uint32((ip.addr.lo^p.ip.addr.lo)>>((32-p.Bits())&63)) == 0
1367 } else {
1368
1369
1370
1371 return ip.addr.xor(p.ip.addr).and(mask6(p.Bits())).isZero()
1372 }
1373 }
1374
1375
1376
1377
1378
1379
1380 func (p Prefix) Overlaps(o Prefix) bool {
1381 if !p.IsValid() || !o.IsValid() {
1382 return false
1383 }
1384 if p == o {
1385 return true
1386 }
1387 if p.ip.Is4() != o.ip.Is4() {
1388 return false
1389 }
1390 var minBits int
1391 if pb, ob := p.Bits(), o.Bits(); pb < ob {
1392 minBits = pb
1393 } else {
1394 minBits = ob
1395 }
1396 if minBits == 0 {
1397 return true
1398 }
1399
1400
1401
1402
1403 var err error
1404 if p, err = p.ip.Prefix(minBits); err != nil {
1405 return false
1406 }
1407 if o, err = o.ip.Prefix(minBits); err != nil {
1408 return false
1409 }
1410 return p.ip == o.ip
1411 }
1412
1413
1414
1415
1416 func (p Prefix) AppendTo(b []byte) []byte {
1417 if p.isZero() {
1418 return b
1419 }
1420 if !p.IsValid() {
1421 return append(b, "invalid Prefix"...)
1422 }
1423
1424
1425 if p.ip.z == z4 {
1426 b = p.ip.appendTo4(b)
1427 } else {
1428 if p.ip.Is4In6() {
1429 b = append(b, "::ffff:"...)
1430 b = p.ip.Unmap().appendTo4(b)
1431 } else {
1432 b = p.ip.appendTo6(b)
1433 }
1434 }
1435
1436 b = append(b, '/')
1437 b = appendDecimal(b, uint8(p.Bits()))
1438 return b
1439 }
1440
1441
1442
1443
1444 func (p Prefix) MarshalText() ([]byte, error) {
1445 var max int
1446 switch p.ip.z {
1447 case z0:
1448 case z4:
1449 max = len("255.255.255.255/32")
1450 default:
1451 max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0/128")
1452 }
1453 b := make([]byte, 0, max)
1454 b = p.AppendTo(b)
1455 return b, nil
1456 }
1457
1458
1459
1460
1461 func (p *Prefix) UnmarshalText(text []byte) error {
1462 if len(text) == 0 {
1463 *p = Prefix{}
1464 return nil
1465 }
1466 var err error
1467 *p, err = ParsePrefix(string(text))
1468 return err
1469 }
1470
1471
1472
1473
1474 func (p Prefix) MarshalBinary() ([]byte, error) {
1475 b := p.Addr().withoutZone().marshalBinaryWithTrailingBytes(1)
1476 b[len(b)-1] = uint8(p.Bits())
1477 return b, nil
1478 }
1479
1480
1481
1482 func (p *Prefix) UnmarshalBinary(b []byte) error {
1483 if len(b) < 1 {
1484 return errors.New("unexpected slice size")
1485 }
1486 var addr Addr
1487 err := addr.UnmarshalBinary(b[:len(b)-1])
1488 if err != nil {
1489 return err
1490 }
1491 *p = PrefixFrom(addr, int(b[len(b)-1]))
1492 return nil
1493 }
1494
1495
1496 func (p Prefix) String() string {
1497 if !p.IsValid() {
1498 return "invalid Prefix"
1499 }
1500 return p.ip.String() + "/" + itoa.Itoa(p.Bits())
1501 }
1502
View as plain text