summaryrefslogtreecommitdiff
path: root/src/pkg/net/ipsock.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/net/ipsock.go')
-rw-r--r--src/pkg/net/ipsock.go29
1 files changed, 22 insertions, 7 deletions
diff --git a/src/pkg/net/ipsock.go b/src/pkg/net/ipsock.go
index 4ba6a55b9..ae4204b48 100644
--- a/src/pkg/net/ipsock.go
+++ b/src/pkg/net/ipsock.go
@@ -18,19 +18,34 @@ import (
// Unfortunately, we need to run on kernels built without IPv6 support too.
// So probe the kernel to figure it out.
func kernelSupportsIPv6() bool {
- // FreeBSD does not support this sort of interface.
- if syscall.OS == "freebsd" {
+ s, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
+ if err != 0 {
return false
}
- fd, e := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
- if fd >= 0 {
- closesocket(fd)
+ defer closesocket(s)
+
+ la := &TCPAddr{IP: IPv4(127, 0, 0, 1)}
+ sa, oserr := la.toAddr().sockaddr(syscall.AF_INET6)
+ if oserr != nil {
+ return false
}
- return e == 0
+
+ return syscall.Bind(s, sa) == 0
}
var preferIPv4 = !kernelSupportsIPv6()
+func firstSupportedAddr(addrs []string) (addr IP) {
+ for _, s := range addrs {
+ addr = ParseIP(s)
+ if !preferIPv4 || addr.To4() != nil {
+ break
+ }
+ addr = nil
+ }
+ return addr
+}
+
// TODO(rsc): if syscall.OS == "linux", we're supposd to read
// /proc/sys/net/core/somaxconn,
// to take advantage of kernels that have raised the limit.
@@ -208,7 +223,7 @@ func hostPortToIP(net, hostport string) (ip IP, iport int, err os.Error) {
err = err1
goto Error
}
- addr = ParseIP(addrs[0])
+ addr = firstSupportedAddr(addrs)
if addr == nil {
// should not happen
err = &AddrError{"LookupHost returned invalid address", addrs[0]}