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