1
0
mirror of https://github.com/golang/go synced 2024-11-25 07:17:56 -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:
Mikio Hara 2011-05-16 23:21:13 -04:00 committed by Russ Cox
parent 5342aedeed
commit db36e03692
3 changed files with 116 additions and 27 deletions

View File

@ -6,7 +6,6 @@ package http
import ( import (
"bufio" "bufio"
"bytes"
"compress/gzip" "compress/gzip"
"crypto/tls" "crypto/tls"
"encoding/base64" "encoding/base64"
@ -309,11 +308,7 @@ func (t *Transport) useProxy(addr string) bool {
return false return false
} }
if ip := net.ParseIP(host); ip != nil { if ip := net.ParseIP(host); ip != nil {
if ip4 := ip.To4(); ip4 != nil && ip4[0] == 127 { if ip.IsLoopback() {
// 127.0.0.0/8 loopback isn't proxied.
return false
}
if bytes.Equal(ip, net.IPv6loopback) {
return false return false
} }
} }

View File

@ -83,6 +83,63 @@ var (
IPv6linklocalallrouters = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02} 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? // Is p all zeros?
func isZeros(p IP) bool { func isZeros(p IP) bool {
for i := 0; i < len(p); i++ { for i := 0; i < len(p); i++ {

View File

@ -9,6 +9,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"os" "os"
"runtime"
) )
func isEqual(a, b []byte) bool { func isEqual(a, b []byte) bool {
@ -31,11 +32,7 @@ var parseiptests = []struct {
{"abc", nil}, {"abc", nil},
{"123:", nil}, {"123:", nil},
{"::ffff:127.0.0.1", IPv4(127, 0, 0, 1)}, {"::ffff:127.0.0.1", IPv4(127, 0, 0, 1)},
{"2001:4860:0:2001::68", {"2001:4860:0:2001::68", IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}},
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)}, {"::ffff:4a7d:1363", IPv4(74, 125, 19, 99)},
} }
@ -52,29 +49,21 @@ var ipstringtests = []struct {
out string out string
}{ }{
// cf. RFC 5952 (A Recommendation for IPv6 Address Text Representation) // cf. RFC 5952 (A Recommendation for IPv6 Address Text Representation)
{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1},
0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1},
"2001:db8::123:12:1"}, "2001:db8::123:12:1"},
{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1},
0, 0, 0, 0, 0, 0, 0, 0x1},
"2001:db8::1"}, "2001:db8::1"},
{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0x1, {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1},
0, 0, 0, 0x1, 0, 0, 0, 0x1},
"2001:db8:0:1:0:1:0:1"}, "2001:db8:0:1:0:1:0:1"},
{IP{0x20, 0x1, 0xd, 0xb8, 0, 0x1, 0, 0, {IP{0x20, 0x1, 0xd, 0xb8, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0},
0, 0x1, 0, 0, 0, 0x1, 0, 0},
"2001:db8:1:0:1:0:1:0"}, "2001:db8:1:0:1:0:1:0"},
{IP{0x20, 0x1, 0, 0, 0, 0, 0, 0, {IP{0x20, 0x1, 0, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1},
0, 0x1, 0, 0, 0, 0, 0, 0x1},
"2001::1:0:0:1"}, "2001::1:0:0:1"},
{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0},
0, 0x1, 0, 0, 0, 0, 0, 0},
"2001:db8:0:0:1::"}, "2001:db8:0:0:1::"},
{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1},
0, 0x1, 0, 0, 0, 0, 0, 0x1},
"2001:db8::1:0:0:1"}, "2001:db8::1:0:0:1"},
{IP{0x20, 0x1, 0xD, 0xB8, 0, 0, 0, 0, {IP{0x20, 0x1, 0xD, 0xB8, 0, 0, 0, 0, 0, 0xA, 0, 0xB, 0, 0xC, 0, 0xD},
0, 0xA, 0, 0xB, 0, 0xC, 0, 0xD},
"2001:db8::a:b:c:d"}, "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)
}
}
}