Commit db36e036 authored by Mikio Hara's avatar Mikio Hara Committed by Russ Cox

net, http: add and make use of IP address scope identification API

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
parent 5342aede
......@@ -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
}
}
......
......@@ -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++ {
......
......@@ -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)
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment