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