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