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

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 027d52134c62 https://go.googlecode.com/hg/ 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
39 Zone string // IPv6 scoped addressing zone
40 } 39 }
41 40
42 // IPv4 returns the IP address (in 16-byte form) of the 41 // IPv4 returns the IP address (in 16-byte form) of the
43 // IPv4 address a.b.c.d. 42 // IPv4 address a.b.c.d.
44 func IPv4(a, b, c, d byte) IP { 43 func IPv4(a, b, c, d byte) IP {
45 p := make(IP, IPv6len) 44 p := make(IP, IPv6len)
46 copy(p, v4InV6Prefix) 45 copy(p, v4InV6Prefix)
47 p[12] = a 46 p[12] = a
48 p[13] = b 47 p[13] = b
49 p[14] = c 48 p[14] = c
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 return nil 215 return nil
217 } 216 }
218 switch true { 217 switch true {
219 case ip[0] < 0x80: 218 case ip[0] < 0x80:
220 return classAMask 219 return classAMask
221 case ip[0] < 0xC0: 220 case ip[0] < 0xC0:
222 return classBMask 221 return classBMask
223 default: 222 default:
224 return classCMask 223 return classCMask
225 } 224 }
226 return nil // not reached
227 } 225 }
228 226
229 func allFF(b []byte) bool { 227 func allFF(b []byte) bool {
230 for _, c := range b { 228 for _, c := range b {
231 if c != 0xff { 229 if c != 0xff {
232 return false 230 return false
233 } 231 }
234 } 232 }
235 return true 233 return true
236 } 234 }
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 return false 424 return false
427 } 425 }
428 for i := 0; i < l; i++ { 426 for i := 0; i < l; i++ {
429 if nn[i]&m[i] != ip[i]&m[i] { 427 if nn[i]&m[i] != ip[i]&m[i] {
430 return false 428 return false
431 } 429 }
432 } 430 }
433 return true 431 return true
434 } 432 }
435 433
436 // String returns the CIDR notation of n like "192.168.100.1/24", 434 // Network returns the address's network name, "ip+net".
437 // "2001:db8::/48" or "fe80::%en0/64" as defined in RFC 4632, RFC 4291 435 func (n *IPNet) Network() string { return "ip+net" }
438 // and RFC 4007. If the mask is not in the canonical form, it returns 436
439 // the string which consists of an IP address, followed by a slash 437 // String returns the CIDR notation of n like "192.168.100.1/24"
438 // or "2001:DB8::/48" as defined in RFC 4632 and RFC 4291.
439 // If the mask is not in the canonical form, it returns the
440 // string which consists of an IP address, followed by a slash
440 // character and a mask expressed as hexadecimal form with no 441 // character and a mask expressed as hexadecimal form with no
441 // punctuation like "192.168.100.1/c000ff00". 442 // punctuation like "192.168.100.1/c000ff00".
442 func (n *IPNet) String() string { 443 func (n *IPNet) String() string {
443 nn, m := networkNumberAndMask(n) 444 nn, m := networkNumberAndMask(n)
444 if nn == nil || m == nil { 445 if nn == nil || m == nil {
445 return "<nil>" 446 return "<nil>"
446 } 447 }
447 s := nn.String()
448 if n.Zone != "" {
449 s += "%" + n.Zone
450 }
451 l := simpleMaskLength(m) 448 l := simpleMaskLength(m)
452 if l == -1 { 449 if l == -1 {
453 » » return s + "/" + m.String() 450 » » return nn.String() + "/" + m.String()
454 » } 451 » }
455 » return s + "/" + itod(uint(l)) 452 » return nn.String() + "/" + itod(uint(l))
456 } 453 }
457
458 // Network returns the address's network name, "ip+net".
459 func (n *IPNet) Network() string { return "ip+net" }
460 454
461 // Parse IPv4 address (d.d.d.d). 455 // Parse IPv4 address (d.d.d.d).
462 func parseIPv4(s string) IP { 456 func parseIPv4(s string) IP {
463 var p [IPv4len]byte 457 var p [IPv4len]byte
464 i := 0 458 i := 0
465 for j := 0; j < IPv4len; j++ { 459 for j := 0; j < IPv4len; j++ {
466 if i >= len(s) { 460 if i >= len(s) {
467 // Missing octets. 461 // Missing octets.
468 return nil 462 return nil
469 } 463 }
(...skipping 12 matching lines...) Expand all
482 return nil 476 return nil
483 } 477 }
484 p[j] = byte(n) 478 p[j] = byte(n)
485 } 479 }
486 if i != len(s) { 480 if i != len(s) {
487 return nil 481 return nil
488 } 482 }
489 return IPv4(p[0], p[1], p[2], p[3]) 483 return IPv4(p[0], p[1], p[2], p[3])
490 } 484 }
491 485
492 // Parse IPv6 address. Many forms. 486 // parseIPv6 parses s as a literal IPv6 address described in RFC 4291
493 // The basic form is a sequence of eight colon-separated 487 // and RFC 5952. It can also parse a literal scoped IPv6 address with
494 // 16-bit hex numbers separated by colons, 488 // zone identifier which is described in RFC 4007 when zoneAllowed is
495 // as in 0123:4567:89ab:cdef:0123:4567:89ab:cdef. 489 // true.
496 // Two exceptions: 490 func parseIPv6(s string, zoneAllowed bool) (ip IP, zone string) {
497 //» * A run of zeros can be replaced with "::". 491 » ip = make(IP, IPv6len)
498 //» * The last 32 bits can be in IPv4 form.
499 // Thus, ::ffff:1.2.3.4 is the IPv4 address 1.2.3.4.
500 func parseIPv6(s string) (IP, string) {
501 » // The IPv6 scoped addressing zone identifer starts after the
502 » // last percent sign.
503 » var zone string
504 » if i := last(s, '%'); i > 0 {
505 » » s, zone = s[:i], s[i+1:]
506 » }
507
508 » ip := make(IP, IPv6len)
509 ellipsis := -1 // position of ellipsis in p 492 ellipsis := -1 // position of ellipsis in p
510 i := 0 // index in string s 493 i := 0 // index in string s
494
495 if zoneAllowed {
496 s, zone = splitHostZone(s)
497 }
511 498
512 // Might have leading ellipsis 499 // Might have leading ellipsis
513 if len(s) >= 2 && s[0] == ':' && s[1] == ':' { 500 if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
514 ellipsis = 0 501 ellipsis = 0
515 i = 2 502 i = 2
516 // Might be only ellipsis 503 // Might be only ellipsis
517 if i == len(s) { 504 if i == len(s) {
518 return ip, zone 505 return ip, zone
519 } 506 }
520 } 507 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 // 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.
605 type ParseError struct { 592 type ParseError struct {
606 Type string 593 Type string
607 Text string 594 Text string
608 } 595 }
609 596
610 func (e *ParseError) Error() string { 597 func (e *ParseError) Error() string {
611 return "invalid " + e.Type + ": " + e.Text 598 return "invalid " + e.Type + ": " + e.Text
612 } 599 }
613 600
614 // ParseIP parses s as an IP address, returning the result. The string 601 // ParseIP parses s as an IP address, returning the result.
615 // s can be in dotted decimal ("74.125.19.99") or IPv6 602 // The string s can be in dotted decimal ("74.125.19.99")
616 // ("2001:4860:0:2001::68") form. If s is not a valid textual 603 // or IPv6 ("2001:4860:0:2001::68") form.
617 // representation of an IP address, ParseIP returns nil. 604 // If s is not a valid textual representation of an IP address,
605 // ParseIP returns nil.
618 func ParseIP(s string) IP { 606 func ParseIP(s string) IP {
619 if ip := parseIPv4(s); ip != nil { 607 if ip := parseIPv4(s); ip != nil {
620 return ip 608 return ip
621 } 609 }
622 » ip, _ := parseIPv6(s) 610 » ip, _ := parseIPv6(s, false)
rsc 2012/12/06 04:43:41 Since we cannot return the %en0 from this function
mikio 2012/12/11 03:28:18 Done.
623 return ip 611 return ip
624 } 612 }
625 613
626 // ParseCIDR parses s as a CIDR notation IP address and mask, like 614 // ParseCIDR parses s as a CIDR notation IP address and mask,
627 // "192.168.100.1/24", "2001:db8::/48" or "fe80::1%en0", as defined in 615 // like "192.168.100.1/24" or "2001:DB8::/48", as defined in
628 // RFC 4632, RFC 4291 and RFC 4007. It returns the IP address and the 616 // RFC 4632 and RFC 4291.
629 // network implied by the IP, mask and IPv6 scoped addressing zone.
630 // 617 //
631 // For example, ParseCIDR("192.168.100.1/16") returns the IP address 618 // It returns the IP address and the network implied by the IP
632 // 192.168.100.1 and the network 192.168.0.0/16. 619 // and mask. For example, ParseCIDR("192.168.100.1/16") returns
620 // the IP address 192.168.100.1 and the network 192.168.0.0/16.
633 func ParseCIDR(s string) (IP, *IPNet, error) { 621 func ParseCIDR(s string) (IP, *IPNet, error) {
634 i := byteIndex(s, '/') 622 i := byteIndex(s, '/')
635 if i < 0 { 623 if i < 0 {
636 return nil, nil, &ParseError{"CIDR address", s} 624 return nil, nil, &ParseError{"CIDR address", s}
637 } 625 }
638 addr, mask := s[:i], s[i+1:] 626 addr, mask := s[:i], s[i+1:]
639 var zone string
640 iplen := IPv4len 627 iplen := IPv4len
641 ip := parseIPv4(addr) 628 ip := parseIPv4(addr)
642 if ip == nil { 629 if ip == nil {
643 iplen = IPv6len 630 iplen = IPv6len
644 » » ip, zone = parseIPv6(addr) 631 » » ip, _ = parseIPv6(addr, false)
645 } 632 }
646 n, i, ok := dtoi(mask, 0) 633 n, i, ok := dtoi(mask, 0)
647 if ip == nil || !ok || i != len(mask) || n < 0 || n > 8*iplen { 634 if ip == nil || !ok || i != len(mask) || n < 0 || n > 8*iplen {
648 return nil, nil, &ParseError{"CIDR address", s} 635 return nil, nil, &ParseError{"CIDR address", s}
649 } 636 }
650 m := CIDRMask(n, 8*iplen) 637 m := CIDRMask(n, 8*iplen)
651 » return ip, &IPNet{IP: ip.Mask(m), Mask: m, Zone: zone}, nil 638 » return ip, &IPNet{IP: ip.Mask(m), Mask: m}, nil
652 } 639 }
LEFTRIGHT

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