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 "internal/bytealg"
18 "internal/byteorder"
19 "internal/itoa"
20 "math"
21 "strconv"
22 "unique"
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 z unique.Handle[addrDetail]
58 }
59
60
61 type addrDetail struct {
62 isV6 bool
63 zoneV6 string
64 }
65
66
67
68 var (
69 z0 unique.Handle[addrDetail]
70 z4 = unique.Make(addrDetail{})
71 z6noz = unique.Make(addrDetail{isV6: true})
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 byteorder.BeUint64(addr[:8]),
106 byteorder.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 func parseIPv4Fields(in string, off, end int, fields []uint8) error {
156 var val, pos int
157 var digLen int
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
171
172
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
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
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
206 func parseIPv6(in string) (Addr, error) {
207 s := in
208
209
210
211
212
213 zone := ""
214 i := bytealg.IndexByteString(s, '%')
215 if i != -1 {
216 s, zone = s[:i], s[i+1:]
217 if zone == "" {
218
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
225
226
227 if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
228 ellipsis = 0
229 s = s[2:]
230
231 if len(s) == 0 {
232 return IPv6Unspecified().WithZone(zone), nil
233 }
234 }
235
236
237 i = 0
238 for i < 16 {
239
240
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
256 return Addr{}, parseAddrError{in: in, msg: "each group must have 4 or less digits", at: s}
257 }
258 if acc > math.MaxUint16 {
259
260 return Addr{}, parseAddrError{in: in, msg: "IPv6 field has value >=2^16", at: s}
261 }
262 }
263 if off == 0 {
264
265 return Addr{}, parseAddrError{in: in, msg: "each colon-separated field must have at least one digit", at: s}
266 }
267
268
269 if off < len(s) && s[off] == '.' {
270 if ellipsis < 0 && i != 12 {
271
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
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
293 ip[i] = byte(acc >> 8)
294 ip[i+1] = byte(acc)
295 i += 2
296
297
298 s = s[off:]
299 if len(s) == 0 {
300 break
301 }
302
303
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
312 if s[0] == ':' {
313 if ellipsis >= 0 {
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 {
319 break
320 }
321 }
322 }
323
324
325 if len(s) != 0 {
326 return Addr{}, parseAddrError{in: in, msg: "trailing garbage after address", at: s}
327 }
328
329
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
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
347
348
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
360
361 func (ip Addr) v4(i uint8) uint8 {
362 return uint8(ip.addr.lo >> ((3 - i) * 8))
363 }
364
365
366
367 func (ip Addr) v6(i uint8) uint8 {
368 return uint8(*(ip.addr.halves()[(i/8)%2]) >> ((7 - i%8) * 8))
369 }
370
371
372
373 func (ip Addr) v6u16(i uint8) uint16 {
374 return uint16(*(ip.addr.halves()[(i/4)%2]) >> ((3 - i%4) * 16))
375 }
376
377
378
379
380
381
382 func (ip Addr) isZero() bool {
383
384
385 return ip.z == z0
386 }
387
388
389
390
391 func (ip Addr) IsValid() bool { return ip.z != z0 }
392
393
394
395
396
397
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
409 func (ip Addr) Zone() string {
410 if ip.z == z0 {
411 return ""
412 }
413 return ip.z.Value().zoneV6
414 }
415
416
417
418
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
454
455
456 func (ip Addr) Less(ip2 Addr) bool { return ip.Compare(ip2) == -1 }
457
458
459
460
461 func (ip Addr) Is4() bool {
462 return ip.z == z4
463 }
464
465
466 func (ip Addr) Is4In6() bool {
467 return ip.Is6() && ip.addr.hi == 0 && ip.addr.lo>>32 == 0xffff
468 }
469
470
471
472 func (ip Addr) Is6() bool {
473 return ip.z != z0 && ip.z != z4
474 }
475
476
477
478
479
480 func (ip Addr) Unmap() Addr {
481 if ip.Is4In6() {
482 ip.z = z4
483 }
484 return ip
485 }
486
487
488
489
490 func (ip Addr) WithZone(zone string) Addr {
491 if !ip.Is6() {
492 return ip
493 }
494 if zone == "" {
495 ip.z = z6noz
496 return ip
497 }
498 ip.z = unique.Make(addrDetail{isV6: true, zoneV6: zone})
499 return ip
500 }
501
502
503
504 func (ip Addr) withoutZone() Addr {
505 if !ip.Is6() {
506 return ip
507 }
508 ip.z = z6noz
509 return ip
510 }
511
512
513 func (ip Addr) hasZone() bool {
514 return ip.z != z0 && ip.z != z4 && ip.z != z6noz
515 }
516
517
518 func (ip Addr) IsLinkLocalUnicast() bool {
519 if ip.Is4In6() {
520 ip = ip.Unmap()
521 }
522
523
524
525 if ip.Is4() {
526 return ip.v4(0) == 169 && ip.v4(1) == 254
527 }
528
529
530 if ip.Is6() {
531 return ip.v6u16(0)&0xffc0 == 0xfe80
532 }
533 return false
534 }
535
536
537 func (ip Addr) IsLoopback() bool {
538 if ip.Is4In6() {
539 ip = ip.Unmap()
540 }
541
542
543
544 if ip.Is4() {
545 return ip.v4(0) == 127
546 }
547
548
549 if ip.Is6() {
550 return ip.addr.hi == 0 && ip.addr.lo == 1
551 }
552 return false
553 }
554
555
556 func (ip Addr) IsMulticast() bool {
557 if ip.Is4In6() {
558 ip = ip.Unmap()
559 }
560
561
562
563 if ip.Is4() {
564 return ip.v4(0)&0xf0 == 0xe0
565 }
566
567
568 if ip.Is6() {
569 return ip.addr.hi>>(64-8) == 0xff
570 }
571 return false
572 }
573
574
575
576 func (ip Addr) IsInterfaceLocalMulticast() bool {
577
578
579 if ip.Is6() && !ip.Is4In6() {
580 return ip.v6u16(0)&0xff0f == 0xff01
581 }
582 return false
583 }
584
585
586 func (ip Addr) IsLinkLocalMulticast() bool {
587 if ip.Is4In6() {
588 ip = ip.Unmap()
589 }
590
591
592
593 if ip.Is4() {
594 return ip.v4(0) == 224 && ip.v4(1) == 0 && ip.v4(2) == 0
595 }
596
597
598 if ip.Is6() {
599 return ip.v6u16(0)&0xff0f == 0xff02
600 }
601 return false
602 }
603
604
605
606
607
608
609
610
611
612
613 func (ip Addr) IsGlobalUnicast() bool {
614 if ip.z == z0 {
615
616 return false
617 }
618
619 if ip.Is4In6() {
620 ip = ip.Unmap()
621 }
622
623
624
625 if ip.Is4() && (ip == IPv4Unspecified() || ip == AddrFrom4([4]byte{255, 255, 255, 255})) {
626 return false
627 }
628
629 return ip != IPv6Unspecified() &&
630 !ip.IsLoopback() &&
631 !ip.IsMulticast() &&
632 !ip.IsLinkLocalUnicast()
633 }
634
635
636
637
638
639 func (ip Addr) IsPrivate() bool {
640 if ip.Is4In6() {
641 ip = ip.Unmap()
642 }
643
644
645 if ip.Is4() {
646
647
648 return ip.v4(0) == 10 ||
649 (ip.v4(0) == 172 && ip.v4(1)&0xf0 == 16) ||
650 (ip.v4(0) == 192 && ip.v4(1) == 168)
651 }
652
653 if ip.Is6() {
654
655
656 return ip.v6(0)&0xfe == 0xfc
657 }
658
659 return false
660 }
661
662
663
664
665
666 func (ip Addr) IsUnspecified() bool {
667 return ip == IPv4Unspecified() || ip == IPv6Unspecified()
668 }
669
670
671
672
673
674
675 func (ip Addr) Prefix(b int) (Prefix, error) {
676 if b < 0 {
677 return Prefix{}, errors.New("negative Prefix bits")
678 }
679 effectiveBits := b
680 switch ip.z {
681 case z0:
682 return Prefix{}, nil
683 case z4:
684 if b > 32 {
685 return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv4")
686 }
687 effectiveBits += 96
688 default:
689 if b > 128 {
690 return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv6")
691 }
692 }
693 ip.addr = ip.addr.and(mask6(effectiveBits))
694 return PrefixFrom(ip, b), nil
695 }
696
697
698
699
700
701
702 func (ip Addr) As16() (a16 [16]byte) {
703 byteorder.BePutUint64(a16[:8], ip.addr.hi)
704 byteorder.BePutUint64(a16[8:], ip.addr.lo)
705 return a16
706 }
707
708
709
710
711 func (ip Addr) As4() (a4 [4]byte) {
712 if ip.z == z4 || ip.Is4In6() {
713 byteorder.BePutUint32(a4[:], uint32(ip.addr.lo))
714 return a4
715 }
716 if ip.z == z0 {
717 panic("As4 called on IP zero value")
718 }
719 panic("As4 called on IPv6 address")
720 }
721
722
723 func (ip Addr) AsSlice() []byte {
724 switch ip.z {
725 case z0:
726 return nil
727 case z4:
728 var ret [4]byte
729 byteorder.BePutUint32(ret[:], uint32(ip.addr.lo))
730 return ret[:]
731 default:
732 var ret [16]byte
733 byteorder.BePutUint64(ret[:8], ip.addr.hi)
734 byteorder.BePutUint64(ret[8:], ip.addr.lo)
735 return ret[:]
736 }
737 }
738
739
740
741 func (ip Addr) Next() Addr {
742 ip.addr = ip.addr.addOne()
743 if ip.Is4() {
744 if uint32(ip.addr.lo) == 0 {
745
746 return Addr{}
747 }
748 } else {
749 if ip.addr.isZero() {
750
751 return Addr{}
752 }
753 }
754 return ip
755 }
756
757
758
759 func (ip Addr) Prev() Addr {
760 if ip.Is4() {
761 if uint32(ip.addr.lo) == 0 {
762 return Addr{}
763 }
764 } else if ip.addr.isZero() {
765 return Addr{}
766 }
767 ip.addr = ip.addr.subOne()
768 return ip
769 }
770
771
772
773
774
775
776
777
778
779
780
781
782
783 func (ip Addr) String() string {
784 switch ip.z {
785 case z0:
786 return "invalid IP"
787 case z4:
788 return ip.string4()
789 default:
790 if ip.Is4In6() {
791 return ip.string4In6()
792 }
793 return ip.string6()
794 }
795 }
796
797
798
799
800 func (ip Addr) AppendTo(b []byte) []byte {
801 switch ip.z {
802 case z0:
803 return b
804 case z4:
805 return ip.appendTo4(b)
806 default:
807 if ip.Is4In6() {
808 return ip.appendTo4In6(b)
809 }
810 return ip.appendTo6(b)
811 }
812 }
813
814
815
816 const digits = "0123456789abcdef"
817
818
819 func appendDecimal(b []byte, x uint8) []byte {
820
821
822
823 if x >= 100 {
824 b = append(b, digits[x/100])
825 }
826 if x >= 10 {
827 b = append(b, digits[x/10%10])
828 }
829 return append(b, digits[x%10])
830 }
831
832
833 func appendHex(b []byte, x uint16) []byte {
834
835
836
837 if x >= 0x1000 {
838 b = append(b, digits[x>>12])
839 }
840 if x >= 0x100 {
841 b = append(b, digits[x>>8&0xf])
842 }
843 if x >= 0x10 {
844 b = append(b, digits[x>>4&0xf])
845 }
846 return append(b, digits[x&0xf])
847 }
848
849
850 func appendHexPad(b []byte, x uint16) []byte {
851 return append(b, digits[x>>12], digits[x>>8&0xf], digits[x>>4&0xf], digits[x&0xf])
852 }
853
854 func (ip Addr) string4() string {
855 const max = len("255.255.255.255")
856 ret := make([]byte, 0, max)
857 ret = ip.appendTo4(ret)
858 return string(ret)
859 }
860
861 func (ip Addr) appendTo4(ret []byte) []byte {
862 ret = appendDecimal(ret, ip.v4(0))
863 ret = append(ret, '.')
864 ret = appendDecimal(ret, ip.v4(1))
865 ret = append(ret, '.')
866 ret = appendDecimal(ret, ip.v4(2))
867 ret = append(ret, '.')
868 ret = appendDecimal(ret, ip.v4(3))
869 return ret
870 }
871
872 func (ip Addr) string4In6() string {
873 const max = len("::ffff:255.255.255.255%enp5s0")
874 ret := make([]byte, 0, max)
875 ret = ip.appendTo4In6(ret)
876 return string(ret)
877 }
878
879 func (ip Addr) appendTo4In6(ret []byte) []byte {
880 ret = append(ret, "::ffff:"...)
881 ret = ip.Unmap().appendTo4(ret)
882 if ip.z != z6noz {
883 ret = append(ret, '%')
884 ret = append(ret, ip.Zone()...)
885 }
886 return ret
887 }
888
889
890
891
892
893
894 func (ip Addr) string6() string {
895
896
897
898
899
900
901
902 const max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
903 ret := make([]byte, 0, max)
904 ret = ip.appendTo6(ret)
905 return string(ret)
906 }
907
908 func (ip Addr) appendTo6(ret []byte) []byte {
909 zeroStart, zeroEnd := uint8(255), uint8(255)
910 for i := uint8(0); i < 8; i++ {
911 j := i
912 for j < 8 && ip.v6u16(j) == 0 {
913 j++
914 }
915 if l := j - i; l >= 2 && l > zeroEnd-zeroStart {
916 zeroStart, zeroEnd = i, j
917 }
918 }
919
920 for i := uint8(0); i < 8; i++ {
921 if i == zeroStart {
922 ret = append(ret, ':', ':')
923 i = zeroEnd
924 if i >= 8 {
925 break
926 }
927 } else if i > 0 {
928 ret = append(ret, ':')
929 }
930
931 ret = appendHex(ret, ip.v6u16(i))
932 }
933
934 if ip.z != z6noz {
935 ret = append(ret, '%')
936 ret = append(ret, ip.Zone()...)
937 }
938 return ret
939 }
940
941
942
943
944 func (ip Addr) StringExpanded() string {
945 switch ip.z {
946 case z0, z4:
947 return ip.String()
948 }
949
950 const size = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
951 ret := make([]byte, 0, size)
952 for i := uint8(0); i < 8; i++ {
953 if i > 0 {
954 ret = append(ret, ':')
955 }
956
957 ret = appendHexPad(ret, ip.v6u16(i))
958 }
959
960 if ip.z != z6noz {
961
962
963 ret = append(ret, '%')
964 ret = append(ret, ip.Zone()...)
965 }
966 return string(ret)
967 }
968
969
970
971
972 func (ip Addr) MarshalText() ([]byte, error) {
973 switch ip.z {
974 case z0:
975 return []byte(""), nil
976 case z4:
977 max := len("255.255.255.255")
978 b := make([]byte, 0, max)
979 return ip.appendTo4(b), nil
980 default:
981 if ip.Is4In6() {
982 max := len("::ffff:255.255.255.255%enp5s0")
983 b := make([]byte, 0, max)
984 return ip.appendTo4In6(b), nil
985 }
986 max := len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
987 b := make([]byte, 0, max)
988 return ip.appendTo6(b), nil
989 }
990 }
991
992
993
994
995
996
997 func (ip *Addr) UnmarshalText(text []byte) error {
998 if len(text) == 0 {
999 *ip = Addr{}
1000 return nil
1001 }
1002 var err error
1003 *ip, err = ParseAddr(string(text))
1004 return err
1005 }
1006
1007 func (ip Addr) marshalBinaryWithTrailingBytes(trailingBytes int) []byte {
1008 var b []byte
1009 switch ip.z {
1010 case z0:
1011 b = make([]byte, trailingBytes)
1012 case z4:
1013 b = make([]byte, 4+trailingBytes)
1014 byteorder.BePutUint32(b, uint32(ip.addr.lo))
1015 default:
1016 z := ip.Zone()
1017 b = make([]byte, 16+len(z)+trailingBytes)
1018 byteorder.BePutUint64(b[:8], ip.addr.hi)
1019 byteorder.BePutUint64(b[8:], ip.addr.lo)
1020 copy(b[16:], z)
1021 }
1022 return b
1023 }
1024
1025
1026
1027
1028
1029 func (ip Addr) MarshalBinary() ([]byte, error) {
1030 return ip.marshalBinaryWithTrailingBytes(0), nil
1031 }
1032
1033
1034
1035 func (ip *Addr) UnmarshalBinary(b []byte) error {
1036 n := len(b)
1037 switch {
1038 case n == 0:
1039 *ip = Addr{}
1040 return nil
1041 case n == 4:
1042 *ip = AddrFrom4([4]byte(b))
1043 return nil
1044 case n == 16:
1045 *ip = AddrFrom16([16]byte(b))
1046 return nil
1047 case n > 16:
1048 *ip = AddrFrom16([16]byte(b[:16])).WithZone(string(b[16:]))
1049 return nil
1050 }
1051 return errors.New("unexpected slice size")
1052 }
1053
1054
1055 type AddrPort struct {
1056 ip Addr
1057 port uint16
1058 }
1059
1060
1061
1062 func AddrPortFrom(ip Addr, port uint16) AddrPort { return AddrPort{ip: ip, port: port} }
1063
1064
1065 func (p AddrPort) Addr() Addr { return p.ip }
1066
1067
1068 func (p AddrPort) Port() uint16 { return p.port }
1069
1070
1071
1072
1073
1074
1075 func splitAddrPort(s string) (ip, port string, v6 bool, err error) {
1076 i := bytealg.LastIndexByteString(s, ':')
1077 if i == -1 {
1078 return "", "", false, errors.New("not an ip:port")
1079 }
1080
1081 ip, port = s[:i], s[i+1:]
1082 if len(ip) == 0 {
1083 return "", "", false, errors.New("no IP")
1084 }
1085 if len(port) == 0 {
1086 return "", "", false, errors.New("no port")
1087 }
1088 if ip[0] == '[' {
1089 if len(ip) < 2 || ip[len(ip)-1] != ']' {
1090 return "", "", false, errors.New("missing ]")
1091 }
1092 ip = ip[1 : len(ip)-1]
1093 v6 = true
1094 }
1095
1096 return ip, port, v6, nil
1097 }
1098
1099
1100
1101
1102
1103 func ParseAddrPort(s string) (AddrPort, error) {
1104 var ipp AddrPort
1105 ip, port, v6, err := splitAddrPort(s)
1106 if err != nil {
1107 return ipp, err
1108 }
1109 port16, err := strconv.ParseUint(port, 10, 16)
1110 if err != nil {
1111 return ipp, errors.New("invalid port " + strconv.Quote(port) + " parsing " + strconv.Quote(s))
1112 }
1113 ipp.port = uint16(port16)
1114 ipp.ip, err = ParseAddr(ip)
1115 if err != nil {
1116 return AddrPort{}, err
1117 }
1118 if v6 && ipp.ip.Is4() {
1119 return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", square brackets can only be used with IPv6 addresses")
1120 } else if !v6 && ipp.ip.Is6() {
1121 return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", IPv6 addresses must be surrounded by square brackets")
1122 }
1123 return ipp, nil
1124 }
1125
1126
1127
1128 func MustParseAddrPort(s string) AddrPort {
1129 ip, err := ParseAddrPort(s)
1130 if err != nil {
1131 panic(err)
1132 }
1133 return ip
1134 }
1135
1136
1137
1138 func (p AddrPort) IsValid() bool { return p.ip.IsValid() }
1139
1140
1141
1142
1143 func (p AddrPort) Compare(p2 AddrPort) int {
1144 if c := p.Addr().Compare(p2.Addr()); c != 0 {
1145 return c
1146 }
1147 return cmp.Compare(p.Port(), p2.Port())
1148 }
1149
1150 func (p AddrPort) String() string {
1151 var b []byte
1152 switch p.ip.z {
1153 case z0:
1154 return "invalid AddrPort"
1155 case z4:
1156 const max = len("255.255.255.255:65535")
1157 b = make([]byte, 0, max)
1158 b = p.ip.appendTo4(b)
1159 default:
1160 if p.ip.Is4In6() {
1161 const max = len("[::ffff:255.255.255.255%enp5s0]:65535")
1162 b = make([]byte, 0, max)
1163 b = append(b, '[')
1164 b = p.ip.appendTo4In6(b)
1165 } else {
1166 const max = len("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0]:65535")
1167 b = make([]byte, 0, max)
1168 b = append(b, '[')
1169 b = p.ip.appendTo6(b)
1170 }
1171 b = append(b, ']')
1172 }
1173 b = append(b, ':')
1174 b = strconv.AppendUint(b, uint64(p.port), 10)
1175 return string(b)
1176 }
1177
1178
1179
1180
1181 func (p AddrPort) AppendTo(b []byte) []byte {
1182 switch p.ip.z {
1183 case z0:
1184 return b
1185 case z4:
1186 b = p.ip.appendTo4(b)
1187 default:
1188 b = append(b, '[')
1189 if p.ip.Is4In6() {
1190 b = p.ip.appendTo4In6(b)
1191 } else {
1192 b = p.ip.appendTo6(b)
1193 }
1194 b = append(b, ']')
1195 }
1196 b = append(b, ':')
1197 b = strconv.AppendUint(b, uint64(p.port), 10)
1198 return b
1199 }
1200
1201
1202
1203
1204 func (p AddrPort) MarshalText() ([]byte, error) {
1205 var max int
1206 switch p.ip.z {
1207 case z0:
1208 case z4:
1209 max = len("255.255.255.255:65535")
1210 default:
1211 max = len("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0]:65535")
1212 }
1213 b := make([]byte, 0, max)
1214 b = p.AppendTo(b)
1215 return b, nil
1216 }
1217
1218
1219
1220
1221 func (p *AddrPort) UnmarshalText(text []byte) error {
1222 if len(text) == 0 {
1223 *p = AddrPort{}
1224 return nil
1225 }
1226 var err error
1227 *p, err = ParseAddrPort(string(text))
1228 return err
1229 }
1230
1231
1232
1233
1234 func (p AddrPort) MarshalBinary() ([]byte, error) {
1235 b := p.Addr().marshalBinaryWithTrailingBytes(2)
1236 byteorder.LePutUint16(b[len(b)-2:], p.Port())
1237 return b, nil
1238 }
1239
1240
1241
1242 func (p *AddrPort) UnmarshalBinary(b []byte) error {
1243 if len(b) < 2 {
1244 return errors.New("unexpected slice size")
1245 }
1246 var addr Addr
1247 err := addr.UnmarshalBinary(b[:len(b)-2])
1248 if err != nil {
1249 return err
1250 }
1251 *p = AddrPortFrom(addr, byteorder.LeUint16(b[len(b)-2:]))
1252 return nil
1253 }
1254
1255
1256
1257
1258
1259 type Prefix struct {
1260 ip Addr
1261
1262
1263
1264 bitsPlusOne uint8
1265 }
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275 func PrefixFrom(ip Addr, bits int) Prefix {
1276 var bitsPlusOne uint8
1277 if !ip.isZero() && bits >= 0 && bits <= ip.BitLen() {
1278 bitsPlusOne = uint8(bits) + 1
1279 }
1280 return Prefix{
1281 ip: ip.withoutZone(),
1282 bitsPlusOne: bitsPlusOne,
1283 }
1284 }
1285
1286
1287 func (p Prefix) Addr() Addr { return p.ip }
1288
1289
1290
1291
1292 func (p Prefix) Bits() int { return int(p.bitsPlusOne) - 1 }
1293
1294
1295
1296
1297 func (p Prefix) IsValid() bool { return p.bitsPlusOne > 0 }
1298
1299 func (p Prefix) isZero() bool { return p == Prefix{} }
1300
1301
1302 func (p Prefix) IsSingleIP() bool { return p.IsValid() && p.Bits() == p.ip.BitLen() }
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312 func (p Prefix) compare(p2 Prefix) int {
1313 if c := cmp.Compare(p.Addr().BitLen(), p2.Addr().BitLen()); c != 0 {
1314 return c
1315 }
1316 if c := cmp.Compare(p.Bits(), p2.Bits()); c != 0 {
1317 return c
1318 }
1319 return p.Addr().Compare(p2.Addr())
1320 }
1321
1322 type parsePrefixError struct {
1323 in string
1324 msg string
1325 }
1326
1327 func (err parsePrefixError) Error() string {
1328 return "netip.ParsePrefix(" + strconv.Quote(err.in) + "): " + err.msg
1329 }
1330
1331
1332
1333
1334
1335
1336
1337
1338 func ParsePrefix(s string) (Prefix, error) {
1339 i := bytealg.LastIndexByteString(s, '/')
1340 if i < 0 {
1341 return Prefix{}, parsePrefixError{in: s, msg: "no '/'"}
1342 }
1343 ip, err := ParseAddr(s[:i])
1344 if err != nil {
1345 return Prefix{}, parsePrefixError{in: s, msg: err.Error()}
1346 }
1347
1348 if ip.Is6() && ip.z != z6noz {
1349 return Prefix{}, parsePrefixError{in: s, msg: "IPv6 zones cannot be present in a prefix"}
1350 }
1351
1352 bitsStr := s[i+1:]
1353
1354
1355 if len(bitsStr) > 1 && (bitsStr[0] < '1' || bitsStr[0] > '9') {
1356 return Prefix{}, parsePrefixError{in: s, msg: "bad bits after slash: " + strconv.Quote(bitsStr)}
1357 }
1358
1359 bits, err := strconv.Atoi(bitsStr)
1360 if err != nil {
1361 return Prefix{}, parsePrefixError{in: s, msg: "bad bits after slash: " + strconv.Quote(bitsStr)}
1362 }
1363 maxBits := 32
1364 if ip.Is6() {
1365 maxBits = 128
1366 }
1367 if bits < 0 || bits > maxBits {
1368 return Prefix{}, parsePrefixError{in: s, msg: "prefix length out of range"}
1369 }
1370 return PrefixFrom(ip, bits), nil
1371 }
1372
1373
1374
1375 func MustParsePrefix(s string) Prefix {
1376 ip, err := ParsePrefix(s)
1377 if err != nil {
1378 panic(err)
1379 }
1380 return ip
1381 }
1382
1383
1384
1385
1386
1387 func (p Prefix) Masked() Prefix {
1388 m, _ := p.ip.Prefix(p.Bits())
1389 return m
1390 }
1391
1392
1393
1394
1395
1396
1397
1398
1399 func (p Prefix) Contains(ip Addr) bool {
1400 if !p.IsValid() || ip.hasZone() {
1401 return false
1402 }
1403 if f1, f2 := p.ip.BitLen(), ip.BitLen(); f1 == 0 || f2 == 0 || f1 != f2 {
1404 return false
1405 }
1406 if ip.Is4() {
1407
1408
1409
1410
1411
1412
1413
1414
1415 return uint32((ip.addr.lo^p.ip.addr.lo)>>((32-p.Bits())&63)) == 0
1416 } else {
1417
1418
1419
1420 return ip.addr.xor(p.ip.addr).and(mask6(p.Bits())).isZero()
1421 }
1422 }
1423
1424
1425
1426
1427
1428
1429 func (p Prefix) Overlaps(o Prefix) bool {
1430 if !p.IsValid() || !o.IsValid() {
1431 return false
1432 }
1433 if p == o {
1434 return true
1435 }
1436 if p.ip.Is4() != o.ip.Is4() {
1437 return false
1438 }
1439 var minBits int
1440 if pb, ob := p.Bits(), o.Bits(); pb < ob {
1441 minBits = pb
1442 } else {
1443 minBits = ob
1444 }
1445 if minBits == 0 {
1446 return true
1447 }
1448
1449
1450
1451
1452 var err error
1453 if p, err = p.ip.Prefix(minBits); err != nil {
1454 return false
1455 }
1456 if o, err = o.ip.Prefix(minBits); err != nil {
1457 return false
1458 }
1459 return p.ip == o.ip
1460 }
1461
1462
1463
1464
1465 func (p Prefix) AppendTo(b []byte) []byte {
1466 if p.isZero() {
1467 return b
1468 }
1469 if !p.IsValid() {
1470 return append(b, "invalid Prefix"...)
1471 }
1472
1473
1474 if p.ip.z == z4 {
1475 b = p.ip.appendTo4(b)
1476 } else {
1477 if p.ip.Is4In6() {
1478 b = append(b, "::ffff:"...)
1479 b = p.ip.Unmap().appendTo4(b)
1480 } else {
1481 b = p.ip.appendTo6(b)
1482 }
1483 }
1484
1485 b = append(b, '/')
1486 b = appendDecimal(b, uint8(p.Bits()))
1487 return b
1488 }
1489
1490
1491
1492
1493 func (p Prefix) MarshalText() ([]byte, error) {
1494 var max int
1495 switch p.ip.z {
1496 case z0:
1497 case z4:
1498 max = len("255.255.255.255/32")
1499 default:
1500 max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0/128")
1501 }
1502 b := make([]byte, 0, max)
1503 b = p.AppendTo(b)
1504 return b, nil
1505 }
1506
1507
1508
1509
1510 func (p *Prefix) UnmarshalText(text []byte) error {
1511 if len(text) == 0 {
1512 *p = Prefix{}
1513 return nil
1514 }
1515 var err error
1516 *p, err = ParsePrefix(string(text))
1517 return err
1518 }
1519
1520
1521
1522
1523 func (p Prefix) MarshalBinary() ([]byte, error) {
1524 b := p.Addr().withoutZone().marshalBinaryWithTrailingBytes(1)
1525 b[len(b)-1] = uint8(p.Bits())
1526 return b, nil
1527 }
1528
1529
1530
1531 func (p *Prefix) UnmarshalBinary(b []byte) error {
1532 if len(b) < 1 {
1533 return errors.New("unexpected slice size")
1534 }
1535 var addr Addr
1536 err := addr.UnmarshalBinary(b[:len(b)-1])
1537 if err != nil {
1538 return err
1539 }
1540 *p = PrefixFrom(addr, int(b[len(b)-1]))
1541 return nil
1542 }
1543
1544
1545 func (p Prefix) String() string {
1546 if !p.IsValid() {
1547 return "invalid Prefix"
1548 }
1549 return p.ip.String() + "/" + itoa.Itoa(p.Bits())
1550 }
1551
View as plain text