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