Source file
src/net/ip.go
Documentation: net
1
2
3
4
5
6
7
8
9
10
11
12
13 package net
14
15 import (
16 "internal/bytealg"
17 "internal/itoa"
18 )
19
20
21 const (
22 IPv4len = 4
23 IPv6len = 16
24 )
25
26
27
28
29
30
31
32
33
34
35 type IP []byte
36
37
38
39
40
41 type IPMask []byte
42
43
44 type IPNet struct {
45 IP IP
46 Mask IPMask
47 }
48
49
50
51 func IPv4(a, b, c, d byte) IP {
52 p := make(IP, IPv6len)
53 copy(p, v4InV6Prefix)
54 p[12] = a
55 p[13] = b
56 p[14] = c
57 p[15] = d
58 return p
59 }
60
61 var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
62
63
64
65 func IPv4Mask(a, b, c, d byte) IPMask {
66 p := make(IPMask, IPv4len)
67 p[0] = a
68 p[1] = b
69 p[2] = c
70 p[3] = d
71 return p
72 }
73
74
75
76
77 func CIDRMask(ones, bits int) IPMask {
78 if bits != 8*IPv4len && bits != 8*IPv6len {
79 return nil
80 }
81 if ones < 0 || ones > bits {
82 return nil
83 }
84 l := bits / 8
85 m := make(IPMask, l)
86 n := uint(ones)
87 for i := 0; i < l; i++ {
88 if n >= 8 {
89 m[i] = 0xff
90 n -= 8
91 continue
92 }
93 m[i] = ^byte(0xff >> n)
94 n = 0
95 }
96 return m
97 }
98
99
100 var (
101 IPv4bcast = IPv4(255, 255, 255, 255)
102 IPv4allsys = IPv4(224, 0, 0, 1)
103 IPv4allrouter = IPv4(224, 0, 0, 2)
104 IPv4zero = IPv4(0, 0, 0, 0)
105 )
106
107
108 var (
109 IPv6zero = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
110 IPv6unspecified = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
111 IPv6loopback = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
112 IPv6interfacelocalallnodes = IP{0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
113 IPv6linklocalallnodes = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
114 IPv6linklocalallrouters = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02}
115 )
116
117
118
119 func (ip IP) IsUnspecified() bool {
120 return ip.Equal(IPv4zero) || ip.Equal(IPv6unspecified)
121 }
122
123
124 func (ip IP) IsLoopback() bool {
125 if ip4 := ip.To4(); ip4 != nil {
126 return ip4[0] == 127
127 }
128 return ip.Equal(IPv6loopback)
129 }
130
131
132
133 func (ip IP) IsPrivate() bool {
134 if ip4 := ip.To4(); ip4 != nil {
135
136
137
138
139
140
141 return ip4[0] == 10 ||
142 (ip4[0] == 172 && ip4[1]&0xf0 == 16) ||
143 (ip4[0] == 192 && ip4[1] == 168)
144 }
145
146
147 return len(ip) == IPv6len && ip[0]&0xfe == 0xfc
148 }
149
150
151 func (ip IP) IsMulticast() bool {
152 if ip4 := ip.To4(); ip4 != nil {
153 return ip4[0]&0xf0 == 0xe0
154 }
155 return len(ip) == IPv6len && ip[0] == 0xff
156 }
157
158
159
160 func (ip IP) IsInterfaceLocalMulticast() bool {
161 return len(ip) == IPv6len && ip[0] == 0xff && ip[1]&0x0f == 0x01
162 }
163
164
165
166 func (ip IP) IsLinkLocalMulticast() bool {
167 if ip4 := ip.To4(); ip4 != nil {
168 return ip4[0] == 224 && ip4[1] == 0 && ip4[2] == 0
169 }
170 return len(ip) == IPv6len && ip[0] == 0xff && ip[1]&0x0f == 0x02
171 }
172
173
174
175 func (ip IP) IsLinkLocalUnicast() bool {
176 if ip4 := ip.To4(); ip4 != nil {
177 return ip4[0] == 169 && ip4[1] == 254
178 }
179 return len(ip) == IPv6len && ip[0] == 0xfe && ip[1]&0xc0 == 0x80
180 }
181
182
183
184
185
186
187
188
189
190 func (ip IP) IsGlobalUnicast() bool {
191 return (len(ip) == IPv4len || len(ip) == IPv6len) &&
192 !ip.Equal(IPv4bcast) &&
193 !ip.IsUnspecified() &&
194 !ip.IsLoopback() &&
195 !ip.IsMulticast() &&
196 !ip.IsLinkLocalUnicast()
197 }
198
199
200 func isZeros(p IP) bool {
201 for i := 0; i < len(p); i++ {
202 if p[i] != 0 {
203 return false
204 }
205 }
206 return true
207 }
208
209
210
211 func (ip IP) To4() IP {
212 if len(ip) == IPv4len {
213 return ip
214 }
215 if len(ip) == IPv6len &&
216 isZeros(ip[0:10]) &&
217 ip[10] == 0xff &&
218 ip[11] == 0xff {
219 return ip[12:16]
220 }
221 return nil
222 }
223
224
225
226 func (ip IP) To16() IP {
227 if len(ip) == IPv4len {
228 return IPv4(ip[0], ip[1], ip[2], ip[3])
229 }
230 if len(ip) == IPv6len {
231 return ip
232 }
233 return nil
234 }
235
236
237 var (
238 classAMask = IPv4Mask(0xff, 0, 0, 0)
239 classBMask = IPv4Mask(0xff, 0xff, 0, 0)
240 classCMask = IPv4Mask(0xff, 0xff, 0xff, 0)
241 )
242
243
244
245
246 func (ip IP) DefaultMask() IPMask {
247 if ip = ip.To4(); ip == nil {
248 return nil
249 }
250 switch {
251 case ip[0] < 0x80:
252 return classAMask
253 case ip[0] < 0xC0:
254 return classBMask
255 default:
256 return classCMask
257 }
258 }
259
260 func allFF(b []byte) bool {
261 for _, c := range b {
262 if c != 0xff {
263 return false
264 }
265 }
266 return true
267 }
268
269
270 func (ip IP) Mask(mask IPMask) IP {
271 if len(mask) == IPv6len && len(ip) == IPv4len && allFF(mask[:12]) {
272 mask = mask[12:]
273 }
274 if len(mask) == IPv4len && len(ip) == IPv6len && bytealg.Equal(ip[:12], v4InV6Prefix) {
275 ip = ip[12:]
276 }
277 n := len(ip)
278 if n != len(mask) {
279 return nil
280 }
281 out := make(IP, n)
282 for i := 0; i < n; i++ {
283 out[i] = ip[i] & mask[i]
284 }
285 return out
286 }
287
288
289
290
291 func ubtoa(dst []byte, start int, v byte) int {
292 if v < 10 {
293 dst[start] = v + '0'
294 return 1
295 } else if v < 100 {
296 dst[start+1] = v%10 + '0'
297 dst[start] = v/10 + '0'
298 return 2
299 }
300
301 dst[start+2] = v%10 + '0'
302 dst[start+1] = (v/10)%10 + '0'
303 dst[start] = v/100 + '0'
304 return 3
305 }
306
307
308
309
310
311
312
313 func (ip IP) String() string {
314 p := ip
315
316 if len(ip) == 0 {
317 return "<nil>"
318 }
319
320
321 if p4 := p.To4(); len(p4) == IPv4len {
322 const maxIPv4StringLen = len("255.255.255.255")
323 b := make([]byte, maxIPv4StringLen)
324
325 n := ubtoa(b, 0, p4[0])
326 b[n] = '.'
327 n++
328
329 n += ubtoa(b, n, p4[1])
330 b[n] = '.'
331 n++
332
333 n += ubtoa(b, n, p4[2])
334 b[n] = '.'
335 n++
336
337 n += ubtoa(b, n, p4[3])
338 return string(b[:n])
339 }
340 if len(p) != IPv6len {
341 return "?" + hexString(ip)
342 }
343
344
345 e0 := -1
346 e1 := -1
347 for i := 0; i < IPv6len; i += 2 {
348 j := i
349 for j < IPv6len && p[j] == 0 && p[j+1] == 0 {
350 j += 2
351 }
352 if j > i && j-i > e1-e0 {
353 e0 = i
354 e1 = j
355 i = j
356 }
357 }
358
359 if e1-e0 <= 2 {
360 e0 = -1
361 e1 = -1
362 }
363
364 const maxLen = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
365 b := make([]byte, 0, maxLen)
366
367
368 for i := 0; i < IPv6len; i += 2 {
369 if i == e0 {
370 b = append(b, ':', ':')
371 i = e1
372 if i >= IPv6len {
373 break
374 }
375 } else if i > 0 {
376 b = append(b, ':')
377 }
378 b = appendHex(b, (uint32(p[i])<<8)|uint32(p[i+1]))
379 }
380 return string(b)
381 }
382
383 func hexString(b []byte) string {
384 s := make([]byte, len(b)*2)
385 for i, tn := range b {
386 s[i*2], s[i*2+1] = hexDigit[tn>>4], hexDigit[tn&0xf]
387 }
388 return string(s)
389 }
390
391
392
393 func ipEmptyString(ip IP) string {
394 if len(ip) == 0 {
395 return ""
396 }
397 return ip.String()
398 }
399
400
401
402
403 func (ip IP) MarshalText() ([]byte, error) {
404 if len(ip) == 0 {
405 return []byte(""), nil
406 }
407 if len(ip) != IPv4len && len(ip) != IPv6len {
408 return nil, &AddrError{Err: "invalid IP address", Addr: hexString(ip)}
409 }
410 return []byte(ip.String()), nil
411 }
412
413
414
415 func (ip *IP) UnmarshalText(text []byte) error {
416 if len(text) == 0 {
417 *ip = nil
418 return nil
419 }
420 s := string(text)
421 x := ParseIP(s)
422 if x == nil {
423 return &ParseError{Type: "IP address", Text: s}
424 }
425 *ip = x
426 return nil
427 }
428
429
430
431
432 func (ip IP) Equal(x IP) bool {
433 if len(ip) == len(x) {
434 return bytealg.Equal(ip, x)
435 }
436 if len(ip) == IPv4len && len(x) == IPv6len {
437 return bytealg.Equal(x[0:12], v4InV6Prefix) && bytealg.Equal(ip, x[12:])
438 }
439 if len(ip) == IPv6len && len(x) == IPv4len {
440 return bytealg.Equal(ip[0:12], v4InV6Prefix) && bytealg.Equal(ip[12:], x)
441 }
442 return false
443 }
444
445 func (ip IP) matchAddrFamily(x IP) bool {
446 return ip.To4() != nil && x.To4() != nil || ip.To16() != nil && ip.To4() == nil && x.To16() != nil && x.To4() == nil
447 }
448
449
450
451 func simpleMaskLength(mask IPMask) int {
452 var n int
453 for i, v := range mask {
454 if v == 0xff {
455 n += 8
456 continue
457 }
458
459
460 for v&0x80 != 0 {
461 n++
462 v <<= 1
463 }
464
465 if v != 0 {
466 return -1
467 }
468 for i++; i < len(mask); i++ {
469 if mask[i] != 0 {
470 return -1
471 }
472 }
473 break
474 }
475 return n
476 }
477
478
479
480
481 func (m IPMask) Size() (ones, bits int) {
482 ones, bits = simpleMaskLength(m), len(m)*8
483 if ones == -1 {
484 return 0, 0
485 }
486 return
487 }
488
489
490 func (m IPMask) String() string {
491 if len(m) == 0 {
492 return "<nil>"
493 }
494 return hexString(m)
495 }
496
497 func networkNumberAndMask(n *IPNet) (ip IP, m IPMask) {
498 if ip = n.IP.To4(); ip == nil {
499 ip = n.IP
500 if len(ip) != IPv6len {
501 return nil, nil
502 }
503 }
504 m = n.Mask
505 switch len(m) {
506 case IPv4len:
507 if len(ip) != IPv4len {
508 return nil, nil
509 }
510 case IPv6len:
511 if len(ip) == IPv4len {
512 m = m[12:]
513 }
514 default:
515 return nil, nil
516 }
517 return
518 }
519
520
521 func (n *IPNet) Contains(ip IP) bool {
522 nn, m := networkNumberAndMask(n)
523 if x := ip.To4(); x != nil {
524 ip = x
525 }
526 l := len(ip)
527 if l != len(nn) {
528 return false
529 }
530 for i := 0; i < l; i++ {
531 if nn[i]&m[i] != ip[i]&m[i] {
532 return false
533 }
534 }
535 return true
536 }
537
538
539 func (n *IPNet) Network() string { return "ip+net" }
540
541
542
543
544
545
546
547 func (n *IPNet) String() string {
548 nn, m := networkNumberAndMask(n)
549 if nn == nil || m == nil {
550 return "<nil>"
551 }
552 l := simpleMaskLength(m)
553 if l == -1 {
554 return nn.String() + "/" + m.String()
555 }
556 return nn.String() + "/" + itoa.Uitoa(uint(l))
557 }
558
559
560 func parseIPv4(s string) IP {
561 var p [IPv4len]byte
562 for i := 0; i < IPv4len; i++ {
563 if len(s) == 0 {
564
565 return nil
566 }
567 if i > 0 {
568 if s[0] != '.' {
569 return nil
570 }
571 s = s[1:]
572 }
573 n, c, ok := dtoi(s)
574 if !ok || n > 0xFF {
575 return nil
576 }
577 if c > 1 && s[0] == '0' {
578
579 return nil
580 }
581 s = s[c:]
582 p[i] = byte(n)
583 }
584 if len(s) != 0 {
585 return nil
586 }
587 return IPv4(p[0], p[1], p[2], p[3])
588 }
589
590
591
592 func parseIPv6Zone(s string) (IP, string) {
593 s, zone := splitHostZone(s)
594 return parseIPv6(s), zone
595 }
596
597
598
599 func parseIPv6(s string) (ip IP) {
600 ip = make(IP, IPv6len)
601 ellipsis := -1
602
603
604 if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
605 ellipsis = 0
606 s = s[2:]
607
608 if len(s) == 0 {
609 return ip
610 }
611 }
612
613
614 i := 0
615 for i < IPv6len {
616
617 n, c, ok := xtoi(s)
618 if !ok || n > 0xFFFF {
619 return nil
620 }
621
622
623 if c < len(s) && s[c] == '.' {
624 if ellipsis < 0 && i != IPv6len-IPv4len {
625
626 return nil
627 }
628 if i+IPv4len > IPv6len {
629
630 return nil
631 }
632 ip4 := parseIPv4(s)
633 if ip4 == nil {
634 return nil
635 }
636 ip[i] = ip4[12]
637 ip[i+1] = ip4[13]
638 ip[i+2] = ip4[14]
639 ip[i+3] = ip4[15]
640 s = ""
641 i += IPv4len
642 break
643 }
644
645
646 ip[i] = byte(n >> 8)
647 ip[i+1] = byte(n)
648 i += 2
649
650
651 s = s[c:]
652 if len(s) == 0 {
653 break
654 }
655
656
657 if s[0] != ':' || len(s) == 1 {
658 return nil
659 }
660 s = s[1:]
661
662
663 if s[0] == ':' {
664 if ellipsis >= 0 {
665 return nil
666 }
667 ellipsis = i
668 s = s[1:]
669 if len(s) == 0 {
670 break
671 }
672 }
673 }
674
675
676 if len(s) != 0 {
677 return nil
678 }
679
680
681 if i < IPv6len {
682 if ellipsis < 0 {
683 return nil
684 }
685 n := IPv6len - i
686 for j := i - 1; j >= ellipsis; j-- {
687 ip[j+n] = ip[j]
688 }
689 for j := ellipsis + n - 1; j >= ellipsis; j-- {
690 ip[j] = 0
691 }
692 } else if ellipsis >= 0 {
693
694 return nil
695 }
696 return ip
697 }
698
699
700
701
702
703
704 func ParseIP(s string) IP {
705 for i := 0; i < len(s); i++ {
706 switch s[i] {
707 case '.':
708 return parseIPv4(s)
709 case ':':
710 return parseIPv6(s)
711 }
712 }
713 return nil
714 }
715
716
717
718 func parseIPZone(s string) (IP, string) {
719 for i := 0; i < len(s); i++ {
720 switch s[i] {
721 case '.':
722 return parseIPv4(s), ""
723 case ':':
724 return parseIPv6Zone(s)
725 }
726 }
727 return nil, ""
728 }
729
730
731
732
733
734
735
736
737
738 func ParseCIDR(s string) (IP, *IPNet, error) {
739 i := bytealg.IndexByteString(s, '/')
740 if i < 0 {
741 return nil, nil, &ParseError{Type: "CIDR address", Text: s}
742 }
743 addr, mask := s[:i], s[i+1:]
744 iplen := IPv4len
745 ip := parseIPv4(addr)
746 if ip == nil {
747 iplen = IPv6len
748 ip = parseIPv6(addr)
749 }
750 n, i, ok := dtoi(mask)
751 if ip == nil || !ok || i != len(mask) || n < 0 || n > 8*iplen {
752 return nil, nil, &ParseError{Type: "CIDR address", Text: s}
753 }
754 m := CIDRMask(n, 8*iplen)
755 return ip, &IPNet{IP: ip.Mask(m), Mask: m}, nil
756 }
757
View as plain text