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 if z := ip.Zone(); z != "" {
772 return "::ffff:" + ip.Unmap().string4() + "%" + z
773 } else {
774 return "::ffff:" + ip.Unmap().string4()
775 }
776 }
777 return ip.string6()
778 }
779 }
780
781
782
783
784 func (ip Addr) AppendTo(b []byte) []byte {
785 switch ip.z {
786 case z0:
787 return b
788 case z4:
789 return ip.appendTo4(b)
790 default:
791 if ip.Is4In6() {
792 b = append(b, "::ffff:"...)
793 b = ip.Unmap().appendTo4(b)
794 if z := ip.Zone(); z != "" {
795 b = append(b, '%')
796 b = append(b, z...)
797 }
798 return b
799 }
800 return ip.appendTo6(b)
801 }
802 }
803
804
805
806 const digits = "0123456789abcdef"
807
808
809 func appendDecimal(b []byte, x uint8) []byte {
810
811
812
813 if x >= 100 {
814 b = append(b, digits[x/100])
815 }
816 if x >= 10 {
817 b = append(b, digits[x/10%10])
818 }
819 return append(b, digits[x%10])
820 }
821
822
823 func appendHex(b []byte, x uint16) []byte {
824
825
826
827 if x >= 0x1000 {
828 b = append(b, digits[x>>12])
829 }
830 if x >= 0x100 {
831 b = append(b, digits[x>>8&0xf])
832 }
833 if x >= 0x10 {
834 b = append(b, digits[x>>4&0xf])
835 }
836 return append(b, digits[x&0xf])
837 }
838
839
840 func appendHexPad(b []byte, x uint16) []byte {
841 return append(b, digits[x>>12], digits[x>>8&0xf], digits[x>>4&0xf], digits[x&0xf])
842 }
843
844 func (ip Addr) string4() string {
845 const max = len("255.255.255.255")
846 ret := make([]byte, 0, max)
847 ret = ip.appendTo4(ret)
848 return string(ret)
849 }
850
851 func (ip Addr) appendTo4(ret []byte) []byte {
852 ret = appendDecimal(ret, ip.v4(0))
853 ret = append(ret, '.')
854 ret = appendDecimal(ret, ip.v4(1))
855 ret = append(ret, '.')
856 ret = appendDecimal(ret, ip.v4(2))
857 ret = append(ret, '.')
858 ret = appendDecimal(ret, ip.v4(3))
859 return ret
860 }
861
862
863
864
865
866
867 func (ip Addr) string6() string {
868
869
870
871
872
873
874
875 const max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
876 ret := make([]byte, 0, max)
877 ret = ip.appendTo6(ret)
878 return string(ret)
879 }
880
881 func (ip Addr) appendTo6(ret []byte) []byte {
882 zeroStart, zeroEnd := uint8(255), uint8(255)
883 for i := uint8(0); i < 8; i++ {
884 j := i
885 for j < 8 && ip.v6u16(j) == 0 {
886 j++
887 }
888 if l := j - i; l >= 2 && l > zeroEnd-zeroStart {
889 zeroStart, zeroEnd = i, j
890 }
891 }
892
893 for i := uint8(0); i < 8; i++ {
894 if i == zeroStart {
895 ret = append(ret, ':', ':')
896 i = zeroEnd
897 if i >= 8 {
898 break
899 }
900 } else if i > 0 {
901 ret = append(ret, ':')
902 }
903
904 ret = appendHex(ret, ip.v6u16(i))
905 }
906
907 if ip.z != z6noz {
908 ret = append(ret, '%')
909 ret = append(ret, ip.Zone()...)
910 }
911 return ret
912 }
913
914
915
916
917 func (ip Addr) StringExpanded() string {
918 switch ip.z {
919 case z0, z4:
920 return ip.String()
921 }
922
923 const size = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
924 ret := make([]byte, 0, size)
925 for i := uint8(0); i < 8; i++ {
926 if i > 0 {
927 ret = append(ret, ':')
928 }
929
930 ret = appendHexPad(ret, ip.v6u16(i))
931 }
932
933 if ip.z != z6noz {
934
935
936 ret = append(ret, '%')
937 ret = append(ret, ip.Zone()...)
938 }
939 return string(ret)
940 }
941
942
943
944
945 func (ip Addr) MarshalText() ([]byte, error) {
946 switch ip.z {
947 case z0:
948 return []byte(""), nil
949 case z4:
950 max := len("255.255.255.255")
951 b := make([]byte, 0, max)
952 return ip.appendTo4(b), nil
953 default:
954 max := len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
955 b := make([]byte, 0, max)
956 if ip.Is4In6() {
957 b = append(b, "::ffff:"...)
958 b = ip.Unmap().appendTo4(b)
959 if z := ip.Zone(); z != "" {
960 b = append(b, '%')
961 b = append(b, z...)
962 }
963 return b, nil
964 }
965 return ip.appendTo6(b), nil
966 }
967
968 }
969
970
971
972
973
974
975 func (ip *Addr) UnmarshalText(text []byte) error {
976 if len(text) == 0 {
977 *ip = Addr{}
978 return nil
979 }
980 var err error
981 *ip, err = ParseAddr(string(text))
982 return err
983 }
984
985 func (ip Addr) marshalBinaryWithTrailingBytes(trailingBytes int) []byte {
986 var b []byte
987 switch ip.z {
988 case z0:
989 b = make([]byte, trailingBytes)
990 case z4:
991 b = make([]byte, 4+trailingBytes)
992 bePutUint32(b, uint32(ip.addr.lo))
993 default:
994 z := ip.Zone()
995 b = make([]byte, 16+len(z)+trailingBytes)
996 bePutUint64(b[:8], ip.addr.hi)
997 bePutUint64(b[8:], ip.addr.lo)
998 copy(b[16:], z)
999 }
1000 return b
1001 }
1002
1003
1004
1005
1006
1007 func (ip Addr) MarshalBinary() ([]byte, error) {
1008 return ip.marshalBinaryWithTrailingBytes(0), nil
1009 }
1010
1011
1012
1013 func (ip *Addr) UnmarshalBinary(b []byte) error {
1014 n := len(b)
1015 switch {
1016 case n == 0:
1017 *ip = Addr{}
1018 return nil
1019 case n == 4:
1020 *ip = AddrFrom4(*(*[4]byte)(b))
1021 return nil
1022 case n == 16:
1023 *ip = ipv6Slice(b)
1024 return nil
1025 case n > 16:
1026 *ip = ipv6Slice(b[:16]).WithZone(string(b[16:]))
1027 return nil
1028 }
1029 return errors.New("unexpected slice size")
1030 }
1031
1032
1033 type AddrPort struct {
1034 ip Addr
1035 port uint16
1036 }
1037
1038
1039
1040 func AddrPortFrom(ip Addr, port uint16) AddrPort { return AddrPort{ip: ip, port: port} }
1041
1042
1043 func (p AddrPort) Addr() Addr { return p.ip }
1044
1045
1046 func (p AddrPort) Port() uint16 { return p.port }
1047
1048
1049
1050
1051
1052
1053 func splitAddrPort(s string) (ip, port string, v6 bool, err error) {
1054 i := stringsLastIndexByte(s, ':')
1055 if i == -1 {
1056 return "", "", false, errors.New("not an ip:port")
1057 }
1058
1059 ip, port = s[:i], s[i+1:]
1060 if len(ip) == 0 {
1061 return "", "", false, errors.New("no IP")
1062 }
1063 if len(port) == 0 {
1064 return "", "", false, errors.New("no port")
1065 }
1066 if ip[0] == '[' {
1067 if len(ip) < 2 || ip[len(ip)-1] != ']' {
1068 return "", "", false, errors.New("missing ]")
1069 }
1070 ip = ip[1 : len(ip)-1]
1071 v6 = true
1072 }
1073
1074 return ip, port, v6, nil
1075 }
1076
1077
1078
1079
1080
1081 func ParseAddrPort(s string) (AddrPort, error) {
1082 var ipp AddrPort
1083 ip, port, v6, err := splitAddrPort(s)
1084 if err != nil {
1085 return ipp, err
1086 }
1087 port16, err := strconv.ParseUint(port, 10, 16)
1088 if err != nil {
1089 return ipp, errors.New("invalid port " + strconv.Quote(port) + " parsing " + strconv.Quote(s))
1090 }
1091 ipp.port = uint16(port16)
1092 ipp.ip, err = ParseAddr(ip)
1093 if err != nil {
1094 return AddrPort{}, err
1095 }
1096 if v6 && ipp.ip.Is4() {
1097 return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", square brackets can only be used with IPv6 addresses")
1098 } else if !v6 && ipp.ip.Is6() {
1099 return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", IPv6 addresses must be surrounded by square brackets")
1100 }
1101 return ipp, nil
1102 }
1103
1104
1105
1106 func MustParseAddrPort(s string) AddrPort {
1107 ip, err := ParseAddrPort(s)
1108 if err != nil {
1109 panic(err)
1110 }
1111 return ip
1112 }
1113
1114
1115 func (p AddrPort) isZero() bool { return p == AddrPort{} }
1116
1117
1118
1119 func (p AddrPort) IsValid() bool { return p.ip.IsValid() }
1120
1121 func (p AddrPort) String() string {
1122 switch p.ip.z {
1123 case z0:
1124 return "invalid AddrPort"
1125 case z4:
1126 a := p.ip.As4()
1127 buf := make([]byte, 0, 21)
1128 for i := range a {
1129 buf = strconv.AppendUint(buf, uint64(a[i]), 10)
1130 buf = append(buf, "...:"[i])
1131 }
1132 buf = strconv.AppendUint(buf, uint64(p.port), 10)
1133 return string(buf)
1134 default:
1135
1136 return joinHostPort(p.ip.String(), itoa.Itoa(int(p.port)))
1137 }
1138 }
1139
1140 func joinHostPort(host, port string) string {
1141
1142
1143 if bytealg.IndexByteString(host, ':') >= 0 {
1144 return "[" + host + "]:" + port
1145 }
1146 return host + ":" + port
1147 }
1148
1149
1150
1151
1152 func (p AddrPort) AppendTo(b []byte) []byte {
1153 switch p.ip.z {
1154 case z0:
1155 return b
1156 case z4:
1157 b = p.ip.appendTo4(b)
1158 default:
1159 if p.ip.Is4In6() {
1160 b = append(b, "[::ffff:"...)
1161 b = p.ip.Unmap().appendTo4(b)
1162 if z := p.ip.Zone(); z != "" {
1163 b = append(b, '%')
1164 b = append(b, z...)
1165 }
1166 } else {
1167 b = append(b, '[')
1168 b = p.ip.appendTo6(b)
1169 }
1170 b = append(b, ']')
1171 }
1172 b = append(b, ':')
1173 b = strconv.AppendUint(b, uint64(p.port), 10)
1174 return b
1175 }
1176
1177
1178
1179
1180 func (p AddrPort) MarshalText() ([]byte, error) {
1181 var max int
1182 switch p.ip.z {
1183 case z0:
1184 case z4:
1185 max = len("255.255.255.255:65535")
1186 default:
1187 max = len("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0]:65535")
1188 }
1189 b := make([]byte, 0, max)
1190 b = p.AppendTo(b)
1191 return b, nil
1192 }
1193
1194
1195
1196
1197 func (p *AddrPort) UnmarshalText(text []byte) error {
1198 if len(text) == 0 {
1199 *p = AddrPort{}
1200 return nil
1201 }
1202 var err error
1203 *p, err = ParseAddrPort(string(text))
1204 return err
1205 }
1206
1207
1208
1209
1210 func (p AddrPort) MarshalBinary() ([]byte, error) {
1211 b := p.Addr().marshalBinaryWithTrailingBytes(2)
1212 lePutUint16(b[len(b)-2:], p.Port())
1213 return b, nil
1214 }
1215
1216
1217
1218 func (p *AddrPort) UnmarshalBinary(b []byte) error {
1219 if len(b) < 2 {
1220 return errors.New("unexpected slice size")
1221 }
1222 var addr Addr
1223 err := addr.UnmarshalBinary(b[:len(b)-2])
1224 if err != nil {
1225 return err
1226 }
1227 *p = AddrPortFrom(addr, leUint16(b[len(b)-2:]))
1228 return nil
1229 }
1230
1231
1232
1233
1234
1235 type Prefix struct {
1236 ip Addr
1237
1238
1239
1240
1241
1242
1243
1244 bits int16
1245 }
1246
1247
1248
1249
1250 const invalidPrefixBits = -1
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260 func PrefixFrom(ip Addr, bits int) Prefix {
1261 if bits < 0 || bits > ip.BitLen() {
1262 bits = invalidPrefixBits
1263 }
1264 b16 := int16(bits)
1265 return Prefix{
1266 ip: ip.withoutZone(),
1267 bits: b16,
1268 }
1269 }
1270
1271
1272 func (p Prefix) Addr() Addr { return p.ip }
1273
1274
1275
1276
1277 func (p Prefix) Bits() int { return int(p.bits) }
1278
1279
1280
1281
1282 func (p Prefix) IsValid() bool { return !p.ip.isZero() && p.bits >= 0 && int(p.bits) <= p.ip.BitLen() }
1283
1284 func (p Prefix) isZero() bool { return p == Prefix{} }
1285
1286
1287 func (p Prefix) IsSingleIP() bool { return p.bits != 0 && int(p.bits) == p.ip.BitLen() }
1288
1289
1290
1291
1292
1293
1294
1295
1296 func ParsePrefix(s string) (Prefix, error) {
1297 i := stringsLastIndexByte(s, '/')
1298 if i < 0 {
1299 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): no '/'")
1300 }
1301 ip, err := ParseAddr(s[:i])
1302 if err != nil {
1303 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): " + err.Error())
1304 }
1305
1306 if ip.Is6() && ip.z != z6noz {
1307 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): IPv6 zones cannot be present in a prefix")
1308 }
1309
1310 bitsStr := s[i+1:]
1311 bits, err := strconv.Atoi(bitsStr)
1312 if err != nil {
1313 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): bad bits after slash: " + strconv.Quote(bitsStr))
1314 }
1315 maxBits := 32
1316 if ip.Is6() {
1317 maxBits = 128
1318 }
1319 if bits < 0 || bits > maxBits {
1320 return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): prefix length out of range")
1321 }
1322 return PrefixFrom(ip, bits), nil
1323 }
1324
1325
1326
1327 func MustParsePrefix(s string) Prefix {
1328 ip, err := ParsePrefix(s)
1329 if err != nil {
1330 panic(err)
1331 }
1332 return ip
1333 }
1334
1335
1336
1337
1338
1339 func (p Prefix) Masked() Prefix {
1340 if m, err := p.ip.Prefix(int(p.bits)); err == nil {
1341 return m
1342 }
1343 return Prefix{}
1344 }
1345
1346
1347
1348
1349
1350
1351
1352
1353 func (p Prefix) Contains(ip Addr) bool {
1354 if !p.IsValid() || ip.hasZone() {
1355 return false
1356 }
1357 if f1, f2 := p.ip.BitLen(), ip.BitLen(); f1 == 0 || f2 == 0 || f1 != f2 {
1358 return false
1359 }
1360 if ip.Is4() {
1361
1362
1363
1364
1365
1366
1367
1368
1369 return uint32((ip.addr.lo^p.ip.addr.lo)>>((32-p.bits)&63)) == 0
1370 } else {
1371
1372
1373
1374 return ip.addr.xor(p.ip.addr).and(mask6(int(p.bits))).isZero()
1375 }
1376 }
1377
1378
1379
1380
1381
1382
1383 func (p Prefix) Overlaps(o Prefix) bool {
1384 if !p.IsValid() || !o.IsValid() {
1385 return false
1386 }
1387 if p == o {
1388 return true
1389 }
1390 if p.ip.Is4() != o.ip.Is4() {
1391 return false
1392 }
1393 var minBits int16
1394 if p.bits < o.bits {
1395 minBits = p.bits
1396 } else {
1397 minBits = o.bits
1398 }
1399 if minBits == 0 {
1400 return true
1401 }
1402
1403
1404
1405
1406 var err error
1407 if p, err = p.ip.Prefix(int(minBits)); err != nil {
1408 return false
1409 }
1410 if o, err = o.ip.Prefix(int(minBits)); err != nil {
1411 return false
1412 }
1413 return p.ip == o.ip
1414 }
1415
1416
1417
1418
1419 func (p Prefix) AppendTo(b []byte) []byte {
1420 if p.isZero() {
1421 return b
1422 }
1423 if !p.IsValid() {
1424 return append(b, "invalid Prefix"...)
1425 }
1426
1427
1428 if p.ip.z == z4 {
1429 b = p.ip.appendTo4(b)
1430 } else {
1431 if p.ip.Is4In6() {
1432 b = append(b, "::ffff:"...)
1433 b = p.ip.Unmap().appendTo4(b)
1434 } else {
1435 b = p.ip.appendTo6(b)
1436 }
1437 }
1438
1439 b = append(b, '/')
1440 b = appendDecimal(b, uint8(p.bits))
1441 return b
1442 }
1443
1444
1445
1446
1447 func (p Prefix) MarshalText() ([]byte, error) {
1448 var max int
1449 switch p.ip.z {
1450 case z0:
1451 case z4:
1452 max = len("255.255.255.255/32")
1453 default:
1454 max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0/128")
1455 }
1456 b := make([]byte, 0, max)
1457 b = p.AppendTo(b)
1458 return b, nil
1459 }
1460
1461
1462
1463
1464 func (p *Prefix) UnmarshalText(text []byte) error {
1465 if len(text) == 0 {
1466 *p = Prefix{}
1467 return nil
1468 }
1469 var err error
1470 *p, err = ParsePrefix(string(text))
1471 return err
1472 }
1473
1474
1475
1476
1477 func (p Prefix) MarshalBinary() ([]byte, error) {
1478 b := p.Addr().withoutZone().marshalBinaryWithTrailingBytes(1)
1479 b[len(b)-1] = uint8(p.Bits())
1480 return b, nil
1481 }
1482
1483
1484
1485 func (p *Prefix) UnmarshalBinary(b []byte) error {
1486 if len(b) < 1 {
1487 return errors.New("unexpected slice size")
1488 }
1489 var addr Addr
1490 err := addr.UnmarshalBinary(b[:len(b)-1])
1491 if err != nil {
1492 return err
1493 }
1494 *p = PrefixFrom(addr, int(b[len(b)-1]))
1495 return nil
1496 }
1497
1498
1499 func (p Prefix) String() string {
1500 if !p.IsValid() {
1501 return "invalid Prefix"
1502 }
1503 return p.ip.String() + "/" + itoa.Itoa(int(p.bits))
1504 }
1505
View as plain text