diff options
Diffstat (limited to 'libgo/go/net/ipsock.go')
-rw-r--r-- | libgo/go/net/ipsock.go | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/libgo/go/net/ipsock.go b/libgo/go/net/ipsock.go index 80bc3eea5da..e8bcac64603 100644 --- a/libgo/go/net/ipsock.go +++ b/libgo/go/net/ipsock.go @@ -35,15 +35,28 @@ func kernelSupportsIPv6() bool { var preferIPv4 = !kernelSupportsIPv6() -func firstSupportedAddr(addrs []string) (addr IP) { +func firstSupportedAddr(filter func(IP) IP, addrs []string) IP { for _, s := range addrs { - addr = ParseIP(s) - if !preferIPv4 || addr.To4() != nil { - break + if addr := filter(ParseIP(s)); addr != nil { + return addr } - addr = nil } - return addr + return nil +} + +func anyaddr(x IP) IP { return x } +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 preferIPv4 is set, it means the IPv6 stack + // cannot take IPv4 addresses directly (we prefer + // to use the IPv4 stack) so reject IPv4 addresses. + if x.To4() != nil && preferIPv4 { + return nil + } + return x } // TODO(rsc): if syscall.OS == "linux", we're supposd to read @@ -131,7 +144,6 @@ func (e InvalidAddrError) String() string { return string(e) } func (e InvalidAddrError) Timeout() bool { return false } func (e InvalidAddrError) Temporary() bool { return false } - func ipToSockaddr(family int, ip IP, port int) (syscall.Sockaddr, os.Error) { switch family { case syscall.AF_INET: @@ -218,13 +230,31 @@ func hostPortToIP(net, hostport string) (ip IP, iport int, err os.Error) { // Try as an IP address. addr = ParseIP(host) if addr == nil { + filter := anyaddr + if len(net) >= 4 && net[3] == '4' { + filter = ipv4only + } else if len(net) >= 4 && net[3] == '6' { + filter = ipv6only + } // Not an IP address. Try as a DNS name. addrs, err1 := LookupHost(host) if err1 != nil { err = err1 goto Error } - addr = firstSupportedAddr(addrs) + if filter == anyaddr { + // We'll take any IP address, but since the dialing code + // does not yet try multiple addresses, prefer to use + // an IPv4 address if possible. This is especially relevant + // if localhost resolves to [ipv6-localhost, ipv4-localhost]. + // Too much code assumes localhost == ipv4-localhost. + addr = firstSupportedAddr(ipv4only, addrs) + if addr == nil { + addr = firstSupportedAddr(anyaddr, addrs) + } + } else { + addr = firstSupportedAddr(filter, addrs) + } if addr == nil { // should not happen err = &AddrError{"LookupHost returned invalid address", addrs[0]} |