Commit f0291a8e authored by Mikio Hara's avatar Mikio Hara

net: make IP address selection work correctly on IPv6-only kernel

Update #3610
Update #5267
Update #5707

R=golang-dev, bradfitz, dave, fvbommel
CC=golang-dev
https://golang.org/cl/11958043
parent 74d2e096
......@@ -8,10 +8,24 @@ package net
import "time"
var supportsIPv6, supportsIPv4map bool
var (
// supportsIPv4 reports whether the platform supports IPv4
// networking functionality.
supportsIPv4 bool
// supportsIPv6 reports whether the platfrom supports IPv6
// networking functionality.
supportsIPv6 bool
// supportsIPv4map reports whether the platform supports
// mapping an IPv4 address inside an IPv6 address at transport
// layer protocols. See RFC 4291, RFC 4038 and RFC 3493.
supportsIPv4map bool
)
func init() {
sysInit()
supportsIPv4 = probeIPv4Stack()
supportsIPv6, supportsIPv4map = probeIPv6Stack()
}
......@@ -41,23 +55,32 @@ func firstSupportedAddr(filter func(IP) IP, addrs []string) IP {
return nil
}
func anyaddr(x IP) IP {
if x4 := x.To4(); x4 != nil {
return x4
}
if supportsIPv6 {
return x
// anyaddr returns IP addresses that we can use with the current
// kernel configuration. It returns nil when ip is not suitable for
// the configuration and an IP address.
func anyaddr(ip IP) IP {
if ip4 := ipv4only(ip); ip4 != nil {
return ip4
}
return ipv6only(ip)
}
// ipv4only returns IPv4 addresses that we can use with the kernel's
// IPv4 addressing modes. It returns IPv4-mapped IPv6 addresses as
// IPv4 addresses and returns other IPv6 address types as nils.
func ipv4only(ip IP) IP {
if supportsIPv4 {
return ip.To4()
}
return nil
}
func ipv4only(x IP) IP { return x.To4() }
func ipv6only(x IP) IP {
// Only return addresses that we can use
// with the kernel's IPv6 addressing modes.
if len(x) == IPv6len && x.To4() == nil && supportsIPv6 {
return x
// ipv6only returns IPv6 addresses that we can use with the kernel's
// IPv6 addressing modes. It returns IPv4-mapped IPv6 addresses as
// nils and returns other IPv6 address types as IPv6 addresses.
func ipv6only(ip IP) IP {
if supportsIPv6 && len(ip) == IPv6len && ip.To4() == nil {
return ip
}
return nil
}
......
......@@ -12,10 +12,18 @@ import (
"syscall"
)
func probeIPv4Stack() bool {
// TODO(mikio): implement this when Plan 9 supports IPv6-only
// kernel.
return true
}
// probeIPv6Stack returns two boolean values. If the first boolean
// value is true, kernel supports basic IPv6 functionality. If the
// second boolean value is true, kernel supports IPv6 IPv4-mapping.
func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
// TODO(mikio): implement this once Plan 9 gets an IPv6
// protocol stack implementation.
return false, false
}
......
......@@ -13,6 +13,17 @@ import (
"time"
)
func probeIPv4Stack() bool {
s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
switch err {
case syscall.EAFNOSUPPORT, syscall.EPROTONOSUPPORT:
return false
case nil:
closesocket(s)
}
return true
}
// Should we try to use the IPv4 socket interface if we're
// only dealing with IPv4 sockets? As long as the host system
// understands IPv6, it's okay to pass IPv4 addresses to the IPv6
......
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