Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(7)

Delta Between Two Patch Sets: src/pkg/net/ip.go

Issue 6816116: code review 6816116: net: support IPv6 scoped addressing zone (Closed)
Left Patch Set: diff -r f5c69f87ef34 https://code.google.com/p/go Created 12 years, 4 months ago
Right Patch Set: diff -r 0f3086c49268 https://code.google.com/p/go Created 12 years ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/net/interface_test.go ('k') | src/pkg/net/ip_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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
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
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
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 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b