LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // IP address manipulations | 5 // IP address manipulations |
6 // | 6 // |
7 // IPv4 addresses are 4 bytes; IPv6 addresses are 16 bytes. | 7 // IPv4 addresses are 4 bytes; IPv6 addresses are 16 bytes. |
8 // An IPv4 address can be converted to an IPv6 address by | 8 // An IPv4 address can be converted to an IPv6 address by |
9 // adding a canonical prefix (10 zeros, 2 0xFFs). | 9 // adding a canonical prefix (10 zeros, 2 0xFFs). |
10 // This library accepts either size of byte array but always | 10 // This library accepts either size of byte slice but always |
11 // returns 16-byte addresses. | 11 // returns 16-byte addresses. |
12 | 12 |
13 package net | 13 package net |
14 | 14 |
15 // IP address lengths (bytes). | 15 // IP address lengths (bytes). |
16 const ( | 16 const ( |
17 IPv4len = 4 | 17 IPv4len = 4 |
18 IPv6len = 16 | 18 IPv6len = 16 |
19 ) | 19 ) |
20 | 20 |
21 // An IP is a single IP address, an array of bytes. | 21 // An IP is a single IP address, a slice of bytes. |
22 // Functions in this package accept either 4-byte (IPv4) | 22 // Functions in this package accept either 4-byte (IPv4) |
23 // or 16-byte (IPv6) arrays as input. | 23 // or 16-byte (IPv6) slices as input. |
24 // | 24 // |
25 // Note that in this documentation, referring to an | 25 // Note that in this documentation, referring to an |
26 // IP address as an IPv4 address or an IPv6 address | 26 // IP address as an IPv4 address or an IPv6 address |
27 // is a semantic property of the address, not just the | 27 // is a semantic property of the address, not just the |
28 // length of the byte array: a 16-byte array can still | 28 // length of the byte slice: a 16-byte slice can still |
29 // be an IPv4 address. | 29 // be an IPv4 address. |
30 type IP []byte | 30 type IP []byte |
31 | 31 |
32 // An IP mask is an IP address. | 32 // An IP mask is an IP address. |
33 type IPMask []byte | 33 type IPMask []byte |
34 | 34 |
35 // An IPNet represents an IP network. | 35 // An IPNet represents an IP network. |
36 type IPNet struct { | 36 type IPNet struct { |
37 IP IP // network number | 37 IP IP // network number |
38 Mask IPMask // network mask | 38 Mask IPMask // network mask |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 return nil | 215 return nil |
216 } | 216 } |
217 switch true { | 217 switch true { |
218 case ip[0] < 0x80: | 218 case ip[0] < 0x80: |
219 return classAMask | 219 return classAMask |
220 case ip[0] < 0xC0: | 220 case ip[0] < 0xC0: |
221 return classBMask | 221 return classBMask |
222 default: | 222 default: |
223 return classCMask | 223 return classCMask |
224 } | 224 } |
225 return nil // not reached | |
226 } | 225 } |
227 | 226 |
228 func allFF(b []byte) bool { | 227 func allFF(b []byte) bool { |
229 for _, c := range b { | 228 for _, c := range b { |
230 if c != 0xff { | 229 if c != 0xff { |
231 return false | 230 return false |
232 } | 231 } |
233 } | 232 } |
234 return true | 233 return true |
235 } | 234 } |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 if l != len(nn) { | 423 if l != len(nn) { |
425 return false | 424 return false |
426 } | 425 } |
427 for i := 0; i < l; i++ { | 426 for i := 0; i < l; i++ { |
428 if nn[i]&m[i] != ip[i]&m[i] { | 427 if nn[i]&m[i] != ip[i]&m[i] { |
429 return false | 428 return false |
430 } | 429 } |
431 } | 430 } |
432 return true | 431 return true |
433 } | 432 } |
| 433 |
| 434 // Network returns the address's network name, "ip+net". |
| 435 func (n *IPNet) Network() string { return "ip+net" } |
434 | 436 |
435 // String returns the CIDR notation of n like "192.168.100.1/24" | 437 // String returns the CIDR notation of n like "192.168.100.1/24" |
436 // or "2001:DB8::/48" as defined in RFC 4632 and RFC 4291. | 438 // or "2001:DB8::/48" as defined in RFC 4632 and RFC 4291. |
437 // If the mask is not in the canonical form, it returns the | 439 // If the mask is not in the canonical form, it returns the |
438 // string which consists of an IP address, followed by a slash | 440 // string which consists of an IP address, followed by a slash |
439 // character and a mask expressed as hexadecimal form with no | 441 // character and a mask expressed as hexadecimal form with no |
440 // punctuation like "192.168.100.1/c000ff00". | 442 // punctuation like "192.168.100.1/c000ff00". |
441 func (n *IPNet) String() string { | 443 func (n *IPNet) String() string { |
442 nn, m := networkNumberAndMask(n) | 444 nn, m := networkNumberAndMask(n) |
443 if nn == nil || m == nil { | 445 if nn == nil || m == nil { |
444 return "<nil>" | 446 return "<nil>" |
445 } | 447 } |
446 l := simpleMaskLength(m) | 448 l := simpleMaskLength(m) |
447 if l == -1 { | 449 if l == -1 { |
448 return nn.String() + "/" + m.String() | 450 return nn.String() + "/" + m.String() |
449 } | 451 } |
450 return nn.String() + "/" + itod(uint(l)) | 452 return nn.String() + "/" + itod(uint(l)) |
451 } | 453 } |
452 | 454 |
453 // Network returns the address's network name, "ip+net". | |
454 func (n *IPNet) Network() string { return "ip+net" } | |
455 | |
456 // Parse IPv4 address (d.d.d.d). | 455 // Parse IPv4 address (d.d.d.d). |
457 func parseIPv4(s string) IP { | 456 func parseIPv4(s string) IP { |
458 var p [IPv4len]byte | 457 var p [IPv4len]byte |
459 i := 0 | 458 i := 0 |
460 for j := 0; j < IPv4len; j++ { | 459 for j := 0; j < IPv4len; j++ { |
461 if i >= len(s) { | 460 if i >= len(s) { |
462 // Missing octets. | 461 // Missing octets. |
463 return nil | 462 return nil |
464 } | 463 } |
465 if j > 0 { | 464 if j > 0 { |
(...skipping 11 matching lines...) Expand all Loading... |
477 return nil | 476 return nil |
478 } | 477 } |
479 p[j] = byte(n) | 478 p[j] = byte(n) |
480 } | 479 } |
481 if i != len(s) { | 480 if i != len(s) { |
482 return nil | 481 return nil |
483 } | 482 } |
484 return IPv4(p[0], p[1], p[2], p[3]) | 483 return IPv4(p[0], p[1], p[2], p[3]) |
485 } | 484 } |
486 | 485 |
487 // Parse IPv6 address. Many forms. | 486 // parseIPv6 parses s as a literal IPv6 address described in RFC 4291 |
488 // The basic form is a sequence of eight colon-separated | 487 // and RFC 5952. It can also parse a literal scoped IPv6 address with |
489 // 16-bit hex numbers separated by colons, | 488 // zone identifier which is described in RFC 4007 when zoneAllowed is |
490 // as in 0123:4567:89ab:cdef:0123:4567:89ab:cdef. | 489 // true. |
491 // Two exceptions: | 490 func parseIPv6(s string, zoneAllowed bool) (ip IP, zone string) { |
492 //» * A run of zeros can be replaced with "::". | 491 » ip = make(IP, IPv6len) |
493 //» * The last 32 bits can be in IPv4 form. | |
494 // Thus, ::ffff:1.2.3.4 is the IPv4 address 1.2.3.4. | |
495 func parseIPv6(s string) IP { | |
496 » p := make(IP, IPv6len) | |
497 ellipsis := -1 // position of ellipsis in p | 492 ellipsis := -1 // position of ellipsis in p |
498 i := 0 // index in string s | 493 i := 0 // index in string s |
| 494 |
| 495 if zoneAllowed { |
| 496 s, zone = splitHostZone(s) |
| 497 } |
499 | 498 |
500 // Might have leading ellipsis | 499 // Might have leading ellipsis |
501 if len(s) >= 2 && s[0] == ':' && s[1] == ':' { | 500 if len(s) >= 2 && s[0] == ':' && s[1] == ':' { |
502 ellipsis = 0 | 501 ellipsis = 0 |
503 i = 2 | 502 i = 2 |
504 // Might be only ellipsis | 503 // Might be only ellipsis |
505 if i == len(s) { | 504 if i == len(s) { |
506 » » » return p | 505 » » » return ip, zone |
507 } | 506 } |
508 } | 507 } |
509 | 508 |
510 // Loop, parsing hex numbers followed by colon. | 509 // Loop, parsing hex numbers followed by colon. |
511 j := 0 | 510 j := 0 |
512 for j < IPv6len { | 511 for j < IPv6len { |
513 // Hex number. | 512 // Hex number. |
514 n, i1, ok := xtoi(s, i) | 513 n, i1, ok := xtoi(s, i) |
515 if !ok || n > 0xFFFF { | 514 if !ok || n > 0xFFFF { |
516 » » » return nil | 515 » » » return nil, zone |
517 } | 516 } |
518 | 517 |
519 // If followed by dot, might be in trailing IPv4. | 518 // If followed by dot, might be in trailing IPv4. |
520 if i1 < len(s) && s[i1] == '.' { | 519 if i1 < len(s) && s[i1] == '.' { |
521 if ellipsis < 0 && j != IPv6len-IPv4len { | 520 if ellipsis < 0 && j != IPv6len-IPv4len { |
522 // Not the right place. | 521 // Not the right place. |
523 » » » » return nil | 522 » » » » return nil, zone |
524 } | 523 } |
525 if j+IPv4len > IPv6len { | 524 if j+IPv4len > IPv6len { |
526 // Not enough room. | 525 // Not enough room. |
527 » » » » return nil | 526 » » » » return nil, zone |
528 » » » } | 527 » » » } |
529 » » » p4 := parseIPv4(s[i:]) | 528 » » » ip4 := parseIPv4(s[i:]) |
530 » » » if p4 == nil { | 529 » » » if ip4 == nil { |
531 » » » » return nil | 530 » » » » return nil, zone |
532 » » » } | 531 » » » } |
533 » » » p[j] = p4[12] | 532 » » » ip[j] = ip4[12] |
534 » » » p[j+1] = p4[13] | 533 » » » ip[j+1] = ip4[13] |
535 » » » p[j+2] = p4[14] | 534 » » » ip[j+2] = ip4[14] |
536 » » » p[j+3] = p4[15] | 535 » » » ip[j+3] = ip4[15] |
537 i = len(s) | 536 i = len(s) |
538 j += IPv4len | 537 j += IPv4len |
539 break | 538 break |
540 } | 539 } |
541 | 540 |
542 // Save this 16-bit chunk. | 541 // Save this 16-bit chunk. |
543 » » p[j] = byte(n >> 8) | 542 » » ip[j] = byte(n >> 8) |
544 » » p[j+1] = byte(n) | 543 » » ip[j+1] = byte(n) |
545 j += 2 | 544 j += 2 |
546 | 545 |
547 // Stop at end of string. | 546 // Stop at end of string. |
548 i = i1 | 547 i = i1 |
549 if i == len(s) { | 548 if i == len(s) { |
550 break | 549 break |
551 } | 550 } |
552 | 551 |
553 // Otherwise must be followed by colon and more. | 552 // Otherwise must be followed by colon and more. |
554 if s[i] != ':' || i+1 == len(s) { | 553 if s[i] != ':' || i+1 == len(s) { |
555 » » » return nil | 554 » » » return nil, zone |
556 } | 555 } |
557 i++ | 556 i++ |
558 | 557 |
559 // Look for ellipsis. | 558 // Look for ellipsis. |
560 if s[i] == ':' { | 559 if s[i] == ':' { |
561 if ellipsis >= 0 { // already have one | 560 if ellipsis >= 0 { // already have one |
562 » » » » return nil | 561 » » » » return nil, zone |
563 } | 562 } |
564 ellipsis = j | 563 ellipsis = j |
565 if i++; i == len(s) { // can be at end | 564 if i++; i == len(s) { // can be at end |
566 break | 565 break |
567 } | 566 } |
568 } | 567 } |
569 } | 568 } |
570 | 569 |
571 // Must have used entire string. | 570 // Must have used entire string. |
572 if i != len(s) { | 571 if i != len(s) { |
573 » » return nil | 572 » » return nil, zone |
574 } | 573 } |
575 | 574 |
576 // If didn't parse enough, expand ellipsis. | 575 // If didn't parse enough, expand ellipsis. |
577 if j < IPv6len { | 576 if j < IPv6len { |
578 if ellipsis < 0 { | 577 if ellipsis < 0 { |
579 » » » return nil | 578 » » » return nil, zone |
580 } | 579 } |
581 n := IPv6len - j | 580 n := IPv6len - j |
582 for k := j - 1; k >= ellipsis; k-- { | 581 for k := j - 1; k >= ellipsis; k-- { |
583 » » » p[k+n] = p[k] | 582 » » » ip[k+n] = ip[k] |
584 } | 583 } |
585 for k := ellipsis + n - 1; k >= ellipsis; k-- { | 584 for k := ellipsis + n - 1; k >= ellipsis; k-- { |
586 » » » p[k] = 0 | 585 » » » ip[k] = 0 |
587 » » } | 586 » » } |
588 » } | 587 » } |
589 » return p | 588 » return ip, zone |
590 } | 589 } |
591 | 590 |
592 // A ParseError represents a malformed text string and the type of string that w
as expected. | 591 // A ParseError represents a malformed text string and the type of string that w
as expected. |
593 type ParseError struct { | 592 type ParseError struct { |
594 Type string | 593 Type string |
595 Text string | 594 Text string |
596 } | 595 } |
597 | 596 |
598 func (e *ParseError) Error() string { | 597 func (e *ParseError) Error() string { |
599 return "invalid " + e.Type + ": " + e.Text | 598 return "invalid " + e.Type + ": " + e.Text |
600 } | |
601 | |
602 func parseIP(s string) IP { | |
603 if p := parseIPv4(s); p != nil { | |
604 return p | |
605 } | |
606 if p := parseIPv6(s); p != nil { | |
607 return p | |
608 } | |
609 return nil | |
610 } | 599 } |
611 | 600 |
612 // ParseIP parses s as an IP address, returning the result. | 601 // ParseIP parses s as an IP address, returning the result. |
613 // The string s can be in dotted decimal ("74.125.19.99") | 602 // The string s can be in dotted decimal ("74.125.19.99") |
614 // or IPv6 ("2001:4860:0:2001::68") form. | 603 // or IPv6 ("2001:4860:0:2001::68") form. |
615 // If s is not a valid textual representation of an IP address, | 604 // If s is not a valid textual representation of an IP address, |
616 // ParseIP returns nil. | 605 // ParseIP returns nil. |
617 func ParseIP(s string) IP { | 606 func ParseIP(s string) IP { |
618 » if p := parseIPv4(s); p != nil { | 607 » if ip := parseIPv4(s); ip != nil { |
619 » » return p | 608 » » return ip |
620 » } | 609 » } |
621 » return parseIPv6(s) | 610 » ip, _ := parseIPv6(s, false) |
622 } | 611 » return ip |
623 | 612 } |
624 // ParseCIDR parses s as a CIDR notation IP address and mask, like | 613 |
625 // "192.168.100.1/24", "2001:DB8::/48" or "2001:DB8::%en0/48" as | 614 // ParseCIDR parses s as a CIDR notation IP address and mask, |
626 // defined in RFC 4632, RFC 4291 and RFC 4007. | 615 // like "192.168.100.1/24" or "2001:DB8::/48", as defined in |
| 616 // RFC 4632 and RFC 4291. |
627 // | 617 // |
628 // It returns the IP address and the network implied by the IP and | 618 // It returns the IP address and the network implied by the IP |
629 // mask. For example, ParseCIDR("192.168.100.1/16") returns the IP | 619 // and mask. For example, ParseCIDR("192.168.100.1/16") returns |
630 // address 192.168.100.1 and the network 192.168.0.0/16. | 620 // the IP address 192.168.100.1 and the network 192.168.0.0/16. |
631 func ParseCIDR(s string) (IP, *IPNet, error) { | 621 func ParseCIDR(s string) (IP, *IPNet, error) { |
632 i := byteIndex(s, '/') | 622 i := byteIndex(s, '/') |
633 if i < 0 { | 623 if i < 0 { |
634 return nil, nil, &ParseError{"CIDR address", s} | 624 return nil, nil, &ParseError{"CIDR address", s} |
635 } | 625 } |
636 » ipstr, maskstr := s[:i], s[i+1:] | 626 » addr, mask := s[:i], s[i+1:] |
637 » // The IPv6 scoped addressing zone identifer starts after the | |
638 » // last percent sign. | |
639 » if i := last(ipstr, '%'); i > 0 { | |
640 » » // Just ignore it for now. | |
641 » » ipstr = ipstr[:i] | |
642 » } | |
643 iplen := IPv4len | 627 iplen := IPv4len |
644 » ip := parseIPv4(ipstr) | 628 » ip := parseIPv4(addr) |
645 if ip == nil { | 629 if ip == nil { |
646 iplen = IPv6len | 630 iplen = IPv6len |
647 » » ip = parseIPv6(ipstr) | 631 » » ip, _ = parseIPv6(addr, false) |
648 » } | 632 » } |
649 » n, i, ok := dtoi(maskstr, 0) | 633 » n, i, ok := dtoi(mask, 0) |
650 » if ip == nil || !ok || i != len(maskstr) || n < 0 || n > 8*iplen { | 634 » if ip == nil || !ok || i != len(mask) || n < 0 || n > 8*iplen { |
651 return nil, nil, &ParseError{"CIDR address", s} | 635 return nil, nil, &ParseError{"CIDR address", s} |
652 } | 636 } |
653 m := CIDRMask(n, 8*iplen) | 637 m := CIDRMask(n, 8*iplen) |
654 » return ip, &IPNet{ip.Mask(m), m}, nil | 638 » return ip, &IPNet{IP: ip.Mask(m), Mask: m}, nil |
655 } | 639 } |
LEFT | RIGHT |