mirror of
https://github.com/golang/go
synced 2024-11-21 13:54:43 -07:00
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
This commit is contained in:
parent
5342aedeed
commit
db36e03692
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user