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 if ip.Is4In6() {
512 ip = ip.Unmap()
513 }
514
515
516
517 if ip.Is4() {
518 return ip.v4(0) == 169 && ip.v4(1) == 254
519 }
520
521
522 if ip.Is6() {
523 return ip.v6u16(0)&0xffc0 == 0xfe80
524 }
525 return false
526 }
527
528
529 func (ip Addr) IsLoopback() bool {
530 if ip.Is4In6() {
531 ip = ip.Unmap()
532 }
533
534
535
536 if ip.Is4() {
537 return ip.v4(0) == 127
538 }
539
540
541 if ip.Is6() {
542 return ip.addr.hi == 0 && ip.addr.lo == 1
543 }
544 return false
545 }
546
547
548 func (ip Addr) IsMulticast() bool {
549 if ip.Is4In6() {
550 ip = ip.Unmap()
551 }
552
553
554
555 if ip.Is4() {
556 return ip.v4(0)&0xf0 == 0xe0
557 }
558
559
560 if ip.Is6() {
561 return ip.addr.hi>>(64-8) == 0xff
562 }
563 return false
564 }
565
566
567
568 func (ip Addr) IsInterfaceLocalMulticast() bool {
569
570
571 if ip.Is6() && !ip.Is4In6() {
572 return ip.v6u16(0)&0xff0f == 0xff01
573 }
574 return false
575 }
576
577
578 func (ip Addr) IsLinkLocalMulticast() bool {
579 if ip.Is4In6() {
580 ip = ip.Unmap()
581 }
582
583
584
585 if ip.Is4() {
586 return ip.v4(0) == 224 && ip.v4(1) == 0 && ip.v4(2) == 0
587 }
588
589
590 if ip.Is6() {
591 return ip.v6u16(0)&0xff0f == 0xff02
592 }
593 return false
594 }
595
596
597
598
599
600
601
602
603
604
605 func (ip Addr) IsGlobalUnicast() bool {
606 if ip.z == z0 {
607
608 return false
609 }
610
611 if ip.Is4In6() {
612 ip = ip.Unmap()
613 }
614
615
616
617 if ip.Is4() && (ip == IPv4Unspecified() || ip == AddrFrom4([4]byte{255, 255, 255, 255})) {
618 return false
619 }
620
621 return ip != IPv6Unspecified() &&
622 !ip.IsLoopback() &&
623 !ip.IsMulticast() &&
624 !ip.IsLinkLocalUnicast()
625 }
626
627
628
629
630
631 func (ip Addr) IsPrivate() bool {
632 if ip.Is4In6() {
633 ip = ip.Unmap()
634 }
635
636
637 if ip.Is4() {
638
639
640 return ip.v4(0) == 10 ||
641 (ip.v4(0) == 172 && ip.v4(1)&0xf0 == 16) ||
642 (ip.v4(0) == 192 && ip.v4(1) == 168)
643 }
644
645 if ip.Is6() {
646
647
648 return ip.v6(0)&0xfe == 0xfc
649 }
650
651 return false
652 }
653
654
655
656
657
658 func (ip Addr) IsUnspecified() bool {
659 return ip == IPv4Unspecified() || ip == IPv6Unspecified()
660 }
661
662
663
664
665
666
667 func (ip Addr) Prefix(b int) (Prefix, error) {
668 if b < 0 {
669 return Prefix{}, errors.New("negative Prefix bits")
670 }
671 effectiveBits := b
672 switch ip.z {
673 case z0:
674 return Prefix{}, nil
675 case z4:
676 if b > 32 {
677 return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv4")
678 }
679 effectiveBits += 96
680 default:
681 if b > 128 {
682 return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv6")
683 }
684 }
685 ip.addr = ip.addr.and(mask6(effectiveBits))
686 return PrefixFrom(ip, b), nil
687 }
688
689
690
691
692
693
694 func (ip Addr) As16() (a16 [16]byte) {
695 bePutUint64(a16[:8], ip.addr.hi)
696 bePutUint64(a16[8:], ip.addr.lo)
697 return a16
698 }
699
700
701
702
703 func (ip Addr) As4() (a4 [4]byte) {
704 if ip.z == z4 || ip.Is4In6() {
705 bePutUint32(a4[:], uint32(ip.addr.lo))
706 return a4
707 }
708 if ip.z == z0 {
709 panic("As4 called on IP zero value")
710 }
711 panic("As4 called on IPv6 address")
712 }
713
714
715 func (ip Addr) AsSlice() []byte {
716 switch ip.z {
717 case z0:
718 return nil
719 case z4:
720 var ret [4]byte
721 bePutUint32(ret[:], uint32(ip.addr.lo))
722 return ret[:]
723 default:
724 var ret [16]byte
725 bePutUint64(ret[:8], ip.addr.hi)
726 bePutUint64(ret[8:], ip.addr.lo)
727 return ret[:]
728 }
729 }
730
731
732
733 func (ip Addr) Next() Addr {
734 ip.addr = ip.addr.addOne()
735 if ip.Is4() {
736 if uint32(ip.addr.lo) == 0 {
737
738 return Addr{}
739 }
740 } else {
741 if ip.addr.isZero() {
742
743 return Addr{}
744 }
745 }
746 return ip
747 }
748
749
750
751 func (ip Addr) Prev() Addr {
752 if ip.Is4() {
753 if uint32(ip.addr.lo) == 0 {
754 return Addr{}
755 }
756 } else if ip.addr.isZero() {
757 return Addr{}
758 }
759 ip.addr = ip.addr.subOne()
760 return ip
761 }
762
763
764
765
766
767
768
769
770
771
772
773
774
775 func (ip Addr) String() string {
776 switch ip.z {
777 case z0:
778 return "invalid IP"
779 case z4:
780 return ip.string4()
781 default:
782 if ip.Is4In6() {
783 if z := ip.Zone(); z != "" {
784 return "::ffff:" + ip.Unmap().string4() + "%" + z
785 } else {
786 return "::ffff:" + ip.Unmap().string4()
787 }
788 }
789 return ip.string6()
790 }
791 }
792
793
794
795
796 func (ip Addr) AppendTo(b []byte) []byte {
797 switch ip.z {
798 case z0:
799 return b
800 case z4:
801 return ip.appendTo4(b)
802 default:
803 if ip.Is4In6() {
804 b = append(b, "::ffff:"...)
805 b = ip.Unmap().appendTo4(b)
806 if z := ip.Zone(); z != "" {
807 b = append(b, '%')
808 b = append(b, z...)
809 }
810 return b
811 }
812 return ip.appendTo6(b)
813 }
814 }
815
816
817
818 const digits = "0123456789abcdef"
819
820
821 func appendDecimal(b []byte, x uint8) []byte {
822
823
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
835 func appendHex(b []byte, x uint16) []byte {
836
837
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
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 := make([]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
875
876
877
878
879 func (ip Addr) string6() string {
880
881
882
883
884
885
886
887 const max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
888 ret := make([]byte, 0, max)
889 ret = ip.appendTo6(ret)
890 return string(ret)
891 }
892
893 func (ip Addr) appendTo6(ret []byte) []byte {
894 zeroStart, zeroEnd := uint8(255), uint8(255)
895 for i := uint8(0); i < 8; i++ {
896 j := i
897 for j < 8 && ip.v6u16(j) == 0 {
898 j++
899 }
900 if l := j - i; l >= 2 && l > zeroEnd-zeroStart {
901 zeroStart, zeroEnd = i, j
902 }
903 }
904
905 for i := uint8(0); i < 8; i++ {
906 if i == zeroStart {
907 ret = append(ret, ':', ':')
908 i = zeroEnd
909 if i >= 8 {
910 break
911 }
912 } else if i > 0 {
913 ret = append(ret, ':')
914 }
915
916 ret = appendHex(ret, ip.v6u16(i))
917 }
918
919 if ip.z != z6noz {
920 ret = append(ret, '%')
921 ret = append(ret, ip.Zone()...)
922 }
923 return ret
924 }
925
926
927
928
929 func (ip Addr) StringExpanded() string {
930 switch ip.z {
931 case z0, z4:
932 return ip.String()
933 }
934
935 const size = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
936 ret := make([]byte, 0, size)
937 for i := uint8(0); i < 8; i++ {
938 if i > 0 {
939 ret = append(ret, ':')
940 }
941
942 ret = appendHexPad(ret, ip.v6u16(i))
943 }
944
945 if ip.z != z6noz {
946
947
948 ret = append(ret, '%')
949 ret = append(ret, ip.Zone()...)
950 }
951 return string(ret)
952 }
953
954
955
956
957 func (ip Addr) MarshalText() ([]byte, error) {
958 switch ip.z {
959 case z0:
960 return []byte(""), nil
961 case z4:
962 max := len("255.255.255.255")
963 b := make([]byte, 0, max)
964 return ip.appendTo4(b), nil
965 default:
966 max := len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
967 b := make([]byte, 0, max)
968 if ip.Is4In6() {
969 b = append(b, "::ffff:"...)
970 b = ip.Unmap().appendTo4(b)
971 if z := ip.Zone(); z != "" {
972 b = append(b, '%')
973 b = append(b, z...)
974 }
975 return b, nil
976 }
977 return ip.appendTo6(b), nil
978 }
979
980 }
981
982
983
984
985
986
987 func (ip *Addr) UnmarshalText(text []byte) error {
988 if len(text) == 0 {
989 *ip = Addr{}
990 return nil
991 }
992 var err error
993 *ip, err = ParseAddr(string(text))
994 return err
995 }
996
997 func (ip Addr) marshalBinaryWithTrailingBytes(trailingBytes int) []byte {
998 var b []byte
999 switch ip.z {
1000 case z0:
1001 b = make([]byte, trailingBytes)
1002 case z4:
1003 b = make([]byte, 4+trailingBytes)
1004 bePutUint32(b, uint32(ip.addr.lo))
1005 default:
1006 z := ip.Zone()
1007 b = make([]byte, 16+len(z)+trailingBytes)
1008 bePutUint64(b[:8], ip.addr.hi)
1009 bePutUint64(b[8:], ip.addr.lo)
1010 copy(b[16:], z)
1011 }
1012 return b
1013 }
1014
1015
1016
1017
1018
1019 func (ip Addr) MarshalBinary() ([]byte, error) {
1020 return ip.marshalBinaryWithTrailingBytes(0), nil
1021 }
1022
1023
1024
1025 func (ip *Addr) UnmarshalBinary(b []byte) error {
1026 n := len(b)
1027 switch {
1028 case n == 0:
1029 *ip = Addr{}
1030 return nil
1031 case n == 4:
1032 *ip = AddrFrom4([4]byte(b))
1033 return nil
1034 case n == 16:
1035 *ip = AddrFrom16([16]byte(b))
1036 return nil
1037 case n > 16:
1038 *ip = AddrFrom16([16]byte(b[:16])).WithZone(string(b[16:]))
1039 return nil
1040 }
1041 return errors.New("unexpected slice size")
1042 }
1043
1044
1045 type AddrPort struct {
1046 ip Addr
1047 port uint16
1048 }
1049
1050
1051
1052 func AddrPortFrom(ip Addr, port uint16) AddrPort { return AddrPort{ip: ip, port: port} }
1053
1054
1055 func (p AddrPort) Addr() Addr { return p.ip }
1056
1057
1058 func (p AddrPort) Port() uint16 { return p.port }
1059
1060
1061
1062
1063
1064
1065 func splitAddrPort(s string) (ip, port string, v6 bool, err error) {
1066 i := bytealg.LastIndexByteString(s, ':')
1067 if i == -1 {
1068 return "", "", false, errors.New("not an ip:port")
1069 }
1070
1071 ip, port = s[:i], s[i+1:]
1072 if len(ip) == 0 {
1073 return "", "", false, errors.New("no IP")
1074 }
1075 if len(port) == 0 {
1076 return "", "", false, errors.New("no port")
1077 }
1078 if ip[0] == '[' {
1079 if len(ip) < 2 || ip[len(ip)-1] != ']' {
1080 return "", "", false, errors.New("missing ]")
1081 }
1082 ip = ip[1 : len(ip)-1]
1083 v6 = true
1084 }
1085
1086 return ip, port, v6, nil
1087 }
1088
1089
1090
1091
1092
1093 func ParseAddrPort(s string) (AddrPort, error) {
1094 var ipp AddrPort
1095 ip, port, v6, err := splitAddrPort(s)
1096 if err != nil {
1097 return ipp, err
1098 }
1099 port16, err := strconv.ParseUint(port, 10, 16)
1100 if err != nil {
1101 return ipp, errors.New("invalid port " + strconv.Quote(port) + " parsing " + strconv.Quote(s))
1102 }
1103 ipp.port = uint16(port16)
1104 ipp.ip, err = ParseAddr(ip)
1105 if err != nil {
1106 return AddrPort{}, err
1107 }
1108 if v6 && ipp.ip.Is4() {
1109 return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", square brackets can only be used with IPv6 addresses")
1110 } else if !v6 && ipp.ip.Is6() {
1111 return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", IPv6 addresses must be surrounded by square brackets")
1112 }
1113 return ipp, nil
1114 }
1115
1116
1117
1118 func MustParseAddrPort(s string) AddrPort {
1119 ip, err := ParseAddrPort(s)
1120 if err != nil {
1121 panic(err)
1122 }
1123 return ip
1124 }
1125
1126
1127
1128 func (p AddrPort) IsValid() bool { return p.ip.IsValid() }
1129
1130
1131
1132
1133 func (p AddrPort) Compare(p2 AddrPort) int {
1134 if c := p.Addr().Compare(p2.Addr()); c != 0 {
1135 return c
1136 }
1137 return cmp.Compare(p.Port(), p2.Port())
1138 }
1139
1140 func (p AddrPort) String() string {
1141 switch p.ip.z {
1142 case z0:
1143 return "invalid AddrPort"
1144 case z4:
1145 const max = len("255.255.255.255:65535")
1146 buf := make([]byte, 0, max)
1147 buf = p.ip.appendTo4(buf)
1148 buf = append(buf, ':')
1149 buf = strconv.AppendUint(buf, uint64(p.port), 10)
1150 return string(buf)
1151 default:
1152
1153 return "[" + p.ip.String() + "]:" + itoa.Uitoa(uint(p.port))
1154 }
1155 }
1156
1157
1158
1159
1160 func (p AddrPort) AppendTo(b []byte) []byte {
1161 switch p.ip.z {
1162 case z0:
1163 return b
1164 case z4:
1165 b = p.ip.appendTo4(b)
1166 default:
1167 if p.ip.Is4In6() {
1168 b = append(b, "[::ffff:"...)
1169 b = p.ip.Unmap().appendTo4(b)
1170 if z := p.ip.Zone(); z != "" {
1171 b = append(b, '%')
1172 b = append(b, z...)
1173 }
1174 } else {
1175 b = append(b, '[')
1176 b = p.ip.appendTo6(b)
1177 }
1178 b = append(b, ']')
1179 }
1180 b = append(b, ':')
1181 b = strconv.AppendUint(b, uint64(p.port), 10)
1182 return b
1183 }
1184
1185
1186
1187
1188 func (p AddrPort) MarshalText() ([]byte, error) {
1189 var max int
1190 switch p.ip.z {
1191 case z0:
1192 case z4:
1193 max = len("255.255.255.255:65535")
1194 default:
1195 max = len("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0]:65535")
1196 }
1197 b := make([]byte, 0, max)
1198 b = p.AppendTo(b)
1199 return b, nil
1200 }
1201
1202
1203
1204
1205 func (p *AddrPort) UnmarshalText(text []byte) error {
1206 if len(text) == 0 {
1207 *p = AddrPort{}
1208 return nil
1209 }
1210 var err error
1211 *p, err = ParseAddrPort(string(text))
1212 return err
1213 }
1214
1215
1216
1217
1218 func (p AddrPort) MarshalBinary() ([]byte, error) {
1219 b := p.Addr().marshalBinaryWithTrailingBytes(2)
1220 lePutUint16(b[len(b)-2:], p.Port())
1221 return b, nil
1222 }
1223
1224
1225
1226 func (p *AddrPort) UnmarshalBinary(b []byte) error {
1227 if len(b) < 2 {
1228 return errors.New("unexpected slice size")
1229 }
1230 var addr Addr
1231 err := addr.UnmarshalBinary(b[:len(b)-2])
1232 if err != nil {
1233 return err
1234 }
1235 *p = AddrPortFrom(addr, leUint16(b[len(b)-2:]))
1236 return nil
1237 }
1238
1239
1240
1241
1242
1243 type Prefix struct {
1244 ip Addr
1245
1246
1247
1248 bitsPlusOne uint8
1249 }
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259 func PrefixFrom(ip Addr, bits int) Prefix {
1260 var bitsPlusOne uint8
1261 if !ip.isZero() && bits >= 0 && bits <= ip.BitLen() {
1262 bitsPlusOne = uint8(bits) + 1
1263 }
1264 return Prefix{
1265 ip: ip.withoutZone(),
1266 bitsPlusOne: bitsPlusOne,
1267 }
1268 }
1269
1270
1271 func (p Prefix) Addr() Addr { return p.ip }
1272
1273
1274
1275
1276 func (p Prefix) Bits() int { return int(p.bitsPlusOne) - 1 }
1277
1278
1279
1280
1281 func (p Prefix) IsValid() bool { return p.bitsPlusOne > 0 }
1282
1283 func (p Prefix) isZero() bool { return p == Prefix{} }
1284
1285
1286 func (p Prefix) IsSingleIP() bool { return p.IsValid() && p.Bits() == p.ip.BitLen() }
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296 func (p Prefix) compare(p2 Prefix) int {
1297 if c := cmp.Compare(p.Addr().BitLen(), p2.Addr().BitLen()); c != 0 {
1298 return c
1299 }
1300 if c := cmp.Compare(p.Bits(), p2.Bits()); c != 0 {
1301 return c
1302 }
1303 return p.Addr().Compare(p2.Addr())
1304 }
1305
1306
1307
1308
1309
1310
1311
1312
1313 func ParsePrefix(s string) (Prefix, error) {
1314 i := bytealg.LastIndexByteString(s, '/')
1315 if i < 0 {
1316 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): no '/'")
1317 }
1318 ip, err := ParseAddr(s[:i])
1319 if err != nil {
1320 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): " + err.Error())
1321 }
1322
1323 if ip.Is6() && ip.z != z6noz {
1324 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): IPv6 zones cannot be present in a prefix")
1325 }
1326
1327 bitsStr := s[i+1:]
1328
1329
1330 if len(bitsStr) > 1 && (bitsStr[0] < '1' || bitsStr[0] > '9') {
1331 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): bad bits after slash: " + strconv.Quote(bitsStr))
1332 }
1333
1334 bits, err := strconv.Atoi(bitsStr)
1335 if err != nil {
1336 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): bad bits after slash: " + strconv.Quote(bitsStr))
1337 }
1338 maxBits := 32
1339 if ip.Is6() {
1340 maxBits = 128
1341 }
1342 if bits < 0 || bits > maxBits {
1343 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): prefix length out of range")
1344 }
1345 return PrefixFrom(ip, bits), nil
1346 }
1347
1348
1349
1350 func MustParsePrefix(s string) Prefix {
1351 ip, err := ParsePrefix(s)
1352 if err != nil {
1353 panic(err)
1354 }
1355 return ip
1356 }
1357
1358
1359
1360
1361
1362 func (p Prefix) Masked() Prefix {
1363 m, _ := p.ip.Prefix(p.Bits())
1364 return m
1365 }
1366
1367
1368
1369
1370
1371
1372
1373
1374 func (p Prefix) Contains(ip Addr) bool {
1375 if !p.IsValid() || ip.hasZone() {
1376 return false
1377 }
1378 if f1, f2 := p.ip.BitLen(), ip.BitLen(); f1 == 0 || f2 == 0 || f1 != f2 {
1379 return false
1380 }
1381 if ip.Is4() {
1382
1383
1384
1385
1386
1387
1388
1389
1390 return uint32((ip.addr.lo^p.ip.addr.lo)>>((32-p.Bits())&63)) == 0
1391 } else {
1392
1393
1394
1395 return ip.addr.xor(p.ip.addr).and(mask6(p.Bits())).isZero()
1396 }
1397 }
1398
1399
1400
1401
1402
1403
1404 func (p Prefix) Overlaps(o Prefix) bool {
1405 if !p.IsValid() || !o.IsValid() {
1406 return false
1407 }
1408 if p == o {
1409 return true
1410 }
1411 if p.ip.Is4() != o.ip.Is4() {
1412 return false
1413 }
1414 var minBits int
1415 if pb, ob := p.Bits(), o.Bits(); pb < ob {
1416 minBits = pb
1417 } else {
1418 minBits = ob
1419 }
1420 if minBits == 0 {
1421 return true
1422 }
1423
1424
1425
1426
1427 var err error
1428 if p, err = p.ip.Prefix(minBits); err != nil {
1429 return false
1430 }
1431 if o, err = o.ip.Prefix(minBits); err != nil {
1432 return false
1433 }
1434 return p.ip == o.ip
1435 }
1436
1437
1438
1439
1440 func (p Prefix) AppendTo(b []byte) []byte {
1441 if p.isZero() {
1442 return b
1443 }
1444 if !p.IsValid() {
1445 return append(b, "invalid Prefix"...)
1446 }
1447
1448
1449 if p.ip.z == z4 {
1450 b = p.ip.appendTo4(b)
1451 } else {
1452 if p.ip.Is4In6() {
1453 b = append(b, "::ffff:"...)
1454 b = p.ip.Unmap().appendTo4(b)
1455 } else {
1456 b = p.ip.appendTo6(b)
1457 }
1458 }
1459
1460 b = append(b, '/')
1461 b = appendDecimal(b, uint8(p.Bits()))
1462 return b
1463 }
1464
1465
1466
1467
1468 func (p Prefix) MarshalText() ([]byte, error) {
1469 var max int
1470 switch p.ip.z {
1471 case z0:
1472 case z4:
1473 max = len("255.255.255.255/32")
1474 default:
1475 max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0/128")
1476 }
1477 b := make([]byte, 0, max)
1478 b = p.AppendTo(b)
1479 return b, nil
1480 }
1481
1482
1483
1484
1485 func (p *Prefix) UnmarshalText(text []byte) error {
1486 if len(text) == 0 {
1487 *p = Prefix{}
1488 return nil
1489 }
1490 var err error
1491 *p, err = ParsePrefix(string(text))
1492 return err
1493 }
1494
1495
1496
1497
1498 func (p Prefix) MarshalBinary() ([]byte, error) {
1499 b := p.Addr().withoutZone().marshalBinaryWithTrailingBytes(1)
1500 b[len(b)-1] = uint8(p.Bits())
1501 return b, nil
1502 }
1503
1504
1505
1506 func (p *Prefix) UnmarshalBinary(b []byte) error {
1507 if len(b) < 1 {
1508 return errors.New("unexpected slice size")
1509 }
1510 var addr Addr
1511 err := addr.UnmarshalBinary(b[:len(b)-1])
1512 if err != nil {
1513 return err
1514 }
1515 *p = PrefixFrom(addr, int(b[len(b)-1]))
1516 return nil
1517 }
1518
1519
1520 func (p Prefix) String() string {
1521 if !p.IsValid() {
1522 return "invalid Prefix"
1523 }
1524 return p.ip.String() + "/" + itoa.Itoa(p.Bits())
1525 }
1526
View as plain text