]> Cypherpunks repositories - gostls13.git/commitdiff
net, http: add and make use of IP address scope identification API
authorMikio Hara <mikioh.mikioh@gmail.com>
Tue, 17 May 2011 03:21:13 +0000 (23:21 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 17 May 2011 03:21:13 +0000 (23:21 -0400)
Add seven methods to IP struct: IsUnspecified, IsLoopback,
IsMulticast, IsInterfaceLocalMulticast, IsLinkLocalMulticast,
IsLinkLocalUnicast and IsGlobalUnicast.

R=bradfitz, rsc
CC=golang-dev
https://golang.org/cl/4515083

src/pkg/http/transport.go
src/pkg/net/ip.go
src/pkg/net/ip_test.go

index 249faabe54fcb0cba511cb4b1489d35fad53b9e0..fa912b1e18d1541f77149b1bfcb648b9abcae693 100644 (file)
@@ -6,7 +6,6 @@ package http
 
 import (
        "bufio"
-       "bytes"
        "compress/gzip"
        "crypto/tls"
        "encoding/base64"
@@ -309,11 +308,7 @@ func (t *Transport) useProxy(addr string) bool {
                return false
        }
        if ip := net.ParseIP(host); ip != nil {
-               if ip4 := ip.To4(); ip4 != nil && ip4[0] == 127 {
-                       // 127.0.0.0/8 loopback isn't proxied.
-                       return false
-               }
-               if bytes.Equal(ip, net.IPv6loopback) {
+               if ip.IsLoopback() {
                        return false
                }
        }
index 4c651aee3a6704bc75ef7a028b5ed0e5bdbffd68..a3000af8ae355f3b576b45004fd8bae62318d5b9 100644 (file)
@@ -83,6 +83,63 @@ var (
        IPv6linklocalallrouters    = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02}
 )
 
+// IsUnspecified returns true if ip is an unspecified address.
+func (ip IP) IsUnspecified() bool {
+       if ip.Equal(IPv4zero) || ip.Equal(IPv6unspecified) {
+               return true
+       }
+       return false
+}
+
+// IsLoopback returns true if ip is a loopback address.
+func (ip IP) IsLoopback() bool {
+       if ip4 := ip.To4(); ip4 != nil && ip4[0] == 127 {
+               return true
+       }
+       return ip.Equal(IPv6loopback)
+}
+
+// IsMulticast returns true if ip is a multicast address.
+func (ip IP) IsMulticast() bool {
+       if ip4 := ip.To4(); ip4 != nil && ip4[0]&0xf0 == 0xe0 {
+               return true
+       }
+       return ip[0] == 0xff
+}
+
+// IsInterfaceLinkLocalMulticast returns true if ip is
+// an interface-local multicast address.
+func (ip IP) IsInterfaceLocalMulticast() bool {
+       return len(ip) == IPv6len && ip[0] == 0xff && ip[1]&0x0f == 0x01
+}
+
+// IsLinkLinkLocalMulticast returns true if ip is a link-local
+// multicast address.
+func (ip IP) IsLinkLocalMulticast() bool {
+       if ip4 := ip.To4(); ip4 != nil && ip4[0] == 224 && ip4[1] == 0 && ip4[2] == 0 {
+               return true
+       }
+       return ip[0] == 0xff && ip[1]&0x0f == 0x02
+}
+
+// IsLinkLinkLocalUnicast returns true if ip is a link-local
+// unicast address.
+func (ip IP) IsLinkLocalUnicast() bool {
+       if ip4 := ip.To4(); ip4 != nil && ip4[0] == 169 && ip4[1] == 254 {
+               return true
+       }
+       return ip[0] == 0xfe && ip[1]&0xc0 == 0x80
+}
+
+// IsGlobalUnicast returns true if ip is a global unicast
+// address.
+func (ip IP) IsGlobalUnicast() bool {
+       return !ip.IsUnspecified() &&
+               !ip.IsLoopback() &&
+               !ip.IsMulticast() &&
+               !ip.IsLinkLocalUnicast()
+}
+
 // Is p all zeros?
 func isZeros(p IP) bool {
        for i := 0; i < len(p); i++ {
index 8a06421cc33e3c495b29c3a45e45d3be035efc7d..b189b10c4fd094c37b0af9453066325410ab6db3 100644 (file)
@@ -9,6 +9,7 @@ import (
        "reflect"
        "testing"
        "os"
+       "runtime"
 )
 
 func isEqual(a, b []byte) bool {
@@ -31,11 +32,7 @@ var parseiptests = []struct {
        {"abc", nil},
        {"123:", nil},
        {"::ffff:127.0.0.1", IPv4(127, 0, 0, 1)},
-       {"2001:4860:0:2001::68",
-               IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01,
-                       0, 0, 0, 0, 0, 0, 0x00, 0x68,
-               },
-       },
+       {"2001:4860:0:2001::68", IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}},
        {"::ffff:4a7d:1363", IPv4(74, 125, 19, 99)},
 }
 
@@ -52,29 +49,21 @@ var ipstringtests = []struct {
        out string
 }{
        // cf. RFC 5952 (A Recommendation for IPv6 Address Text Representation)
-       {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0,
-               0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1},
+       {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1},
                "2001:db8::123:12:1"},
-       {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0x1},
+       {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1},
                "2001:db8::1"},
-       {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0x1,
-               0, 0, 0, 0x1, 0, 0, 0, 0x1},
+       {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1},
                "2001:db8:0:1:0:1:0:1"},
-       {IP{0x20, 0x1, 0xd, 0xb8, 0, 0x1, 0, 0,
-               0, 0x1, 0, 0, 0, 0x1, 0, 0},
+       {IP{0x20, 0x1, 0xd, 0xb8, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0},
                "2001:db8:1:0:1:0:1:0"},
-       {IP{0x20, 0x1, 0, 0, 0, 0, 0, 0,
-               0, 0x1, 0, 0, 0, 0, 0, 0x1},
+       {IP{0x20, 0x1, 0, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1},
                "2001::1:0:0:1"},
-       {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0,
-               0, 0x1, 0, 0, 0, 0, 0, 0},
+       {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0},
                "2001:db8:0:0:1::"},
-       {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0,
-               0, 0x1, 0, 0, 0, 0, 0, 0x1},
+       {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1},
                "2001:db8::1:0:0:1"},
-       {IP{0x20, 0x1, 0xD, 0xB8, 0, 0, 0, 0,
-               0, 0xA, 0, 0xB, 0, 0xC, 0, 0xD},
+       {IP{0x20, 0x1, 0xD, 0xB8, 0, 0, 0, 0, 0, 0xA, 0, 0xB, 0, 0xC, 0, 0xD},
                "2001:db8::a:b:c:d"},
 }
 
@@ -176,3 +165,51 @@ func TestIPAddrFamily(t *testing.T) {
                }
        }
 }
+
+var ipscopetests = []struct {
+       scope func(IP) bool
+       in    IP
+       ok    bool
+}{
+       {IP.IsUnspecified, IPv4zero, true},
+       {IP.IsUnspecified, IPv4(127, 0, 0, 1), false},
+       {IP.IsUnspecified, IPv6unspecified, true},
+       {IP.IsUnspecified, IPv6interfacelocalallnodes, false},
+       {IP.IsLoopback, IPv4(127, 0, 0, 1), true},
+       {IP.IsLoopback, IPv4(127, 255, 255, 254), true},
+       {IP.IsLoopback, IPv4(128, 1, 2, 3), false},
+       {IP.IsLoopback, IPv6loopback, true},
+       {IP.IsLoopback, IPv6linklocalallrouters, false},
+       {IP.IsMulticast, IPv4(224, 0, 0, 0), true},
+       {IP.IsMulticast, IPv4(239, 0, 0, 0), true},
+       {IP.IsMulticast, IPv4(240, 0, 0, 0), false},
+       {IP.IsMulticast, IPv6linklocalallnodes, true},
+       {IP.IsMulticast, IP{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, true},
+       {IP.IsMulticast, IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
+       {IP.IsLinkLocalMulticast, IPv4(224, 0, 0, 0), true},
+       {IP.IsLinkLocalMulticast, IPv4(239, 0, 0, 0), false},
+       {IP.IsLinkLocalMulticast, IPv6linklocalallrouters, true},
+       {IP.IsLinkLocalMulticast, IP{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
+       {IP.IsLinkLocalUnicast, IPv4(169, 254, 0, 0), true},
+       {IP.IsLinkLocalUnicast, IPv4(169, 255, 0, 0), false},
+       {IP.IsLinkLocalUnicast, IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, true},
+       {IP.IsLinkLocalUnicast, IP{0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
+       {IP.IsGlobalUnicast, IPv4(240, 0, 0, 0), true},
+       {IP.IsGlobalUnicast, IPv4(232, 0, 0, 0), false},
+       {IP.IsGlobalUnicast, IPv4(169, 254, 0, 0), false},
+       {IP.IsGlobalUnicast, IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1}, true},
+       {IP.IsGlobalUnicast, IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
+       {IP.IsGlobalUnicast, IP{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
+}
+
+func name(f interface{}) string {
+       return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
+}
+
+func TestIPAddrScope(t *testing.T) {
+       for _, tt := range ipscopetests {
+               if ok := tt.scope(tt.in); ok != tt.ok {
+                       t.Errorf("%s(%#q) = %v, want %v", name(tt.scope), tt.in, ok, tt.ok)
+               }
+       }
+}