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