1
2
3
4
5
6
7
8
9
10
11
12
13 package net
14
15 import "os"
16
17
18 const (
19 IPv4len = 4
20 IPv6len = 16
21 )
22
23
24
25
26
27
28
29
30
31
32
33
34
35 type IP []byte
36
37
38 type IPMask []byte
39
40
41
42 func IPv4(a, b, c, d byte) IP {
43 p := make(IP, IPv6len)
44 copy(p, v4InV6Prefix)
45 p[12] = a
46 p[13] = b
47 p[14] = c
48 p[15] = d
49 return p
50 }
51
52 var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
53
54
55
56 func IPv4Mask(a, b, c, d byte) IPMask {
57 p := make(IPMask, IPv6len)
58 for i := 0; i < 12; i++ {
59 p[i] = 0xff
60 }
61 p[12] = a
62 p[13] = b
63 p[14] = c
64 p[15] = d
65 return p
66 }
67
68
69 var (
70 IPv4bcast = IPv4(255, 255, 255, 255)
71 IPv4allsys = IPv4(224, 0, 0, 1)
72 IPv4allrouter = IPv4(224, 0, 0, 2)
73 IPv4zero = IPv4(0, 0, 0, 0)
74 )
75
76
77 var (
78 IPv6zero = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
79 IPv6unspecified = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
80 IPv6loopback = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
81 IPv6interfacelocalallnodes = IP{0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
82 IPv6linklocalallnodes = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
83 IPv6linklocalallrouters = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02}
84 )
85
86
87 func (ip IP) IsUnspecified() bool {
88 if ip.Equal(IPv4zero) || ip.Equal(IPv6unspecified) {
89 return true
90 }
91 return false
92 }
93
94
95 func (ip IP) IsLoopback() bool {
96 if ip4 := ip.To4(); ip4 != nil && ip4[0] == 127 {
97 return true
98 }
99 return ip.Equal(IPv6loopback)
100 }
101
102
103 func (ip IP) IsMulticast() bool {
104 if ip4 := ip.To4(); ip4 != nil && ip4[0]&0xf0 == 0xe0 {
105 return true
106 }
107 return ip[0] == 0xff
108 }
109
110
111
112 func (ip IP) IsInterfaceLocalMulticast() bool {
113 return len(ip) == IPv6len && ip[0] == 0xff && ip[1]&0x0f == 0x01
114 }
115
116
117
118 func (ip IP) IsLinkLocalMulticast() bool {
119 if ip4 := ip.To4(); ip4 != nil && ip4[0] == 224 && ip4[1] == 0 && ip4[2] == 0 {
120 return true
121 }
122 return ip[0] == 0xff && ip[1]&0x0f == 0x02
123 }
124
125
126
127 func (ip IP) IsLinkLocalUnicast() bool {
128 if ip4 := ip.To4(); ip4 != nil && ip4[0] == 169 && ip4[1] == 254 {
129 return true
130 }
131 return ip[0] == 0xfe && ip[1]&0xc0 == 0x80
132 }
133
134
135
136 func (ip IP) IsGlobalUnicast() bool {
137 return !ip.IsUnspecified() &&
138 !ip.IsLoopback() &&
139 !ip.IsMulticast() &&
140 !ip.IsLinkLocalUnicast()
141 }
142
143
144 func isZeros(p IP) bool {
145 for i := 0; i < len(p); i++ {
146 if p[i] != 0 {
147 return false
148 }
149 }
150 return true
151 }
152
153
154
155 func (ip IP) To4() IP {
156 if len(ip) == IPv4len {
157 return ip
158 }
159 if len(ip) == IPv6len &&
160 isZeros(ip[0:10]) &&
161 ip[10] == 0xff &&
162 ip[11] == 0xff {
163 return ip[12:16]
164 }
165 return nil
166 }
167
168
169
170 func (ip IP) To16() IP {
171 if len(ip) == IPv4len {
172 return IPv4(ip[0], ip[1], ip[2], ip[3])
173 }
174 if len(ip) == IPv6len {
175 return ip
176 }
177 return nil
178 }
179
180
181 var (
182 classAMask = IPv4Mask(0xff, 0, 0, 0)
183 classBMask = IPv4Mask(0xff, 0xff, 0, 0)
184 classCMask = IPv4Mask(0xff, 0xff, 0xff, 0)
185 )
186
187
188
189
190 func (ip IP) DefaultMask() IPMask {
191 if ip = ip.To4(); ip == nil {
192 return nil
193 }
194 switch true {
195 case ip[0] < 0x80:
196 return classAMask
197 case ip[0] < 0xC0:
198 return classBMask
199 default:
200 return classCMask
201 }
202 return nil
203 }
204
205 func allFF(b []byte) bool {
206 for _, c := range b {
207 if c != 0xff {
208 return false
209 }
210 }
211 return true
212 }
213
214
215 func (ip IP) Mask(mask IPMask) IP {
216 n := len(ip)
217 if len(mask) == 16 && len(ip) == 4 && allFF(mask[:12]) {
218 mask = mask[12:]
219 }
220 if len(mask) == 4 && len(ip) == 16 && bytesEqual(ip[:12], v4InV6Prefix) {
221 ip = ip[12:]
222 }
223 if n != len(mask) {
224 return nil
225 }
226 out := make(IP, n)
227 for i := 0; i < n; i++ {
228 out[i] = ip[i] & mask[i]
229 }
230 return out
231 }
232
233
234 func itod(i uint) string {
235 if i == 0 {
236 return "0"
237 }
238
239
240 var b [32]byte
241 bp := len(b)
242 for ; i > 0; i /= 10 {
243 bp--
244 b[bp] = byte(i%10) + '0'
245 }
246
247 return string(b[bp:])
248 }
249
250
251 func itox(i uint) string {
252 if i == 0 {
253 return "0"
254 }
255
256
257 var b [32]byte
258 bp := len(b)
259 for ; i > 0; i /= 16 {
260 bp--
261 b[bp] = "0123456789abcdef"[byte(i%16)]
262 }
263
264 return string(b[bp:])
265 }
266
267
268
269
270
271 func (ip IP) String() string {
272 p := ip
273
274 if len(ip) == 0 {
275 return ""
276 }
277
278
279 if p4 := p.To4(); len(p4) == 4 {
280 return itod(uint(p4[0])) + "." +
281 itod(uint(p4[1])) + "." +
282 itod(uint(p4[2])) + "." +
283 itod(uint(p4[3]))
284 }
285 if len(p) != IPv6len {
286 return "?"
287 }
288
289
290 e0 := -1
291 e1 := -1
292 for i := 0; i < 16; i += 2 {
293 j := i
294 for j < 16 && p[j] == 0 && p[j+1] == 0 {
295 j += 2
296 }
297 if j > i && j-i > e1-e0 {
298 e0 = i
299 e1 = j
300 }
301 }
302
303 if e1-e0 <= 2 {
304 e0 = -1
305 e1 = -1
306 }
307
308
309 var s string
310 for i := 0; i < 16; i += 2 {
311 if i == e0 {
312 s += "::"
313 i = e1
314 if i >= 16 {
315 break
316 }
317 } else if i > 0 {
318 s += ":"
319 }
320 s += itox((uint(p[i]) << 8) | uint(p[i+1]))
321 }
322 return s
323 }
324
325
326
327
328 func (ip IP) Equal(x IP) bool {
329 if len(ip) == len(x) {
330 return bytesEqual(ip, x)
331 }
332 if len(ip) == 4 && len(x) == 16 {
333 return bytesEqual(x[0:12], v4InV6Prefix) && bytesEqual(ip, x[12:])
334 }
335 if len(ip) == 16 && len(x) == 4 {
336 return bytesEqual(ip[0:12], v4InV6Prefix) && bytesEqual(ip[12:], x)
337 }
338 return false
339 }
340
341 func bytesEqual(x, y []byte) bool {
342 if len(x) != len(y) {
343 return false
344 }
345 for i, b := range x {
346 if y[i] != b {
347 return false
348 }
349 }
350 return true
351 }
352
353
354
355 func simpleMaskLength(mask IPMask) int {
356 var n int
357 for i, v := range mask {
358 if v == 0xff {
359 n += 8
360 continue
361 }
362
363
364 for v&0x80 != 0 {
365 n++
366 v <<= 1
367 }
368
369 if v != 0 {
370 return -1
371 }
372 for i++; i < len(mask); i++ {
373 if mask[i] != 0 {
374 return -1
375 }
376 }
377 break
378 }
379 return n
380 }
381
382
383
384
385
386
387 func (mask IPMask) String() string {
388 switch len(mask) {
389 case 4:
390 n := simpleMaskLength(mask)
391 if n >= 0 {
392 return itod(uint(n + (IPv6len-IPv4len)*8))
393 }
394 case 16:
395 n := simpleMaskLength(mask)
396 if n >= 12*8 {
397 return itod(uint(n - 12*8))
398 }
399 }
400 return IP(mask).String()
401 }
402
403
404 func parseIPv4(s string) IP {
405 var p [IPv4len]byte
406 i := 0
407 for j := 0; j < IPv4len; j++ {
408 if i >= len(s) {
409
410 return nil
411 }
412 if j > 0 {
413 if s[i] != '.' {
414 return nil
415 }
416 i++
417 }
418 var (
419 n int
420 ok bool
421 )
422 n, i, ok = dtoi(s, i)
423 if !ok || n > 0xFF {
424 return nil
425 }
426 p[j] = byte(n)
427 }
428 if i != len(s) {
429 return nil
430 }
431 return IPv4(p[0], p[1], p[2], p[3])
432 }
433
434
435
436
437
438
439
440
441
442 func parseIPv6(s string) IP {
443 p := make(IP, 16)
444 ellipsis := -1
445 i := 0
446
447
448 if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
449 ellipsis = 0
450 i = 2
451
452 if i == len(s) {
453 return p
454 }
455 }
456
457
458 j := 0
459 for j < IPv6len {
460
461 n, i1, ok := xtoi(s, i)
462 if !ok || n > 0xFFFF {
463 return nil
464 }
465
466
467 if i1 < len(s) && s[i1] == '.' {
468 if ellipsis < 0 && j != IPv6len-IPv4len {
469
470 return nil
471 }
472 if j+IPv4len > IPv6len {
473
474 return nil
475 }
476 p4 := parseIPv4(s[i:])
477 if p4 == nil {
478 return nil
479 }
480 p[j] = p4[12]
481 p[j+1] = p4[13]
482 p[j+2] = p4[14]
483 p[j+3] = p4[15]
484 i = len(s)
485 j += 4
486 break
487 }
488
489
490 p[j] = byte(n >> 8)
491 p[j+1] = byte(n)
492 j += 2
493
494
495 i = i1
496 if i == len(s) {
497 break
498 }
499
500
501 if s[i] != ':' || i+1 == len(s) {
502 return nil
503 }
504 i++
505
506
507 if s[i] == ':' {
508 if ellipsis >= 0 {
509 return nil
510 }
511 ellipsis = j
512 if i++; i == len(s) {
513 break
514 }
515 }
516 }
517
518
519 if i != len(s) {
520 return nil
521 }
522
523
524 if j < IPv6len {
525 if ellipsis < 0 {
526 return nil
527 }
528 n := IPv6len - j
529 for k := j - 1; k >= ellipsis; k-- {
530 p[k+n] = p[k]
531 }
532 for k := ellipsis + n - 1; k >= ellipsis; k-- {
533 p[k] = 0
534 }
535 }
536 return p
537 }
538
539
540 type ParseError struct {
541 Type string
542 Text string
543 }
544
545 func (e *ParseError) String() string {
546 return "invalid " + e.Type + ": " + e.Text
547 }
548
549 func parseIP(s string) IP {
550 if p := parseIPv4(s); p != nil {
551 return p
552 }
553 if p := parseIPv6(s); p != nil {
554 return p
555 }
556 return nil
557 }
558
559
560
561
562
563
564 func ParseIP(s string) IP {
565 if p := parseIPv4(s); p != nil {
566 return p
567 }
568 return parseIPv6(s)
569 }
570
571
572
573
574 func ParseCIDR(s string) (ip IP, mask IPMask, err os.Error) {
575 i := byteIndex(s, '/')
576 if i < 0 {
577 return nil, nil, &ParseError{"CIDR address", s}
578 }
579 ipstr, maskstr := s[:i], s[i+1:]
580 iplen := 4
581 ip = parseIPv4(ipstr)
582 if ip == nil {
583 iplen = 16
584 ip = parseIPv6(ipstr)
585 }
586 nn, i, ok := dtoi(maskstr, 0)
587 if ip == nil || !ok || i != len(maskstr) || nn < 0 || nn > 8*iplen {
588 return nil, nil, &ParseError{"CIDR address", s}
589 }
590 n := uint(nn)
591 if iplen == 4 {
592 v4mask := ^uint32(0xffffffff >> n)
593 mask = IPv4Mask(byte(v4mask>>24), byte(v4mask>>16), byte(v4mask>>8), byte(v4mask))
594 } else {
595 mask = make(IPMask, 16)
596 for i := 0; i < 16; i++ {
597 if n >= 8 {
598 mask[i] = 0xff
599 n -= 8
600 continue
601 }
602 mask[i] = ^byte(0xff >> n)
603 n = 0
604
605 }
606 }
607
608 for i := range ip {
609 if ip[i]&^mask[i] != 0 {
610 return nil, nil, &ParseError{"CIDR address", s}
611 }
612 }
613 return ip, mask, nil
614 }