net: enable SO_REUSEADDR, SO_REUSEPORT options on stream, multicast listeners only

This CL changes default SOL_SOCKET settings to mitigate connect
failure on OpenBSD or similar platforms which support randomized
transport protocol port number assignment.

Fixes #2830.

R=rsc, jsing
CC=golang-dev
https://golang.org/cl/5648044
diff --git a/src/pkg/net/sock_bsd.go b/src/pkg/net/sock_bsd.go
index 7c693a2..2607b04 100644
--- a/src/pkg/net/sock_bsd.go
+++ b/src/pkg/net/sock_bsd.go
@@ -38,6 +38,11 @@
 		return la, nil
 	}
 	switch v := a.(type) {
+	case *TCPAddr, *UnixAddr:
+		err := setDefaultListenerSockopts(s)
+		if err != nil {
+			return nil, err
+		}
 	case *UDPAddr:
 		if v.IP.IsMulticast() {
 			err := setDefaultMulticastSockopts(s)
diff --git a/src/pkg/net/sock_linux.go b/src/pkg/net/sock_linux.go
index 0743843..e509d93 100644
--- a/src/pkg/net/sock_linux.go
+++ b/src/pkg/net/sock_linux.go
@@ -32,6 +32,11 @@
 		return la, nil
 	}
 	switch v := a.(type) {
+	case *TCPAddr, *UnixAddr:
+		err := setDefaultListenerSockopts(s)
+		if err != nil {
+			return nil, err
+		}
 	case *UDPAddr:
 		if v.IP.IsMulticast() {
 			err := setDefaultMulticastSockopts(s)
diff --git a/src/pkg/net/sock_windows.go b/src/pkg/net/sock_windows.go
index 434122c..cce6181 100644
--- a/src/pkg/net/sock_windows.go
+++ b/src/pkg/net/sock_windows.go
@@ -19,6 +19,11 @@
 		return la, nil
 	}
 	switch v := a.(type) {
+	case *TCPAddr, *UnixAddr:
+		err := setDefaultListenerSockopts(s)
+		if err != nil {
+			return nil, err
+		}
 	case *UDPAddr:
 		if v.IP.IsMulticast() {
 			err := setDefaultMulticastSockopts(s)
diff --git a/src/pkg/net/sockopt_bsd.go b/src/pkg/net/sockopt_bsd.go
index bc76465..519d2fb 100644
--- a/src/pkg/net/sockopt_bsd.go
+++ b/src/pkg/net/sockopt_bsd.go
@@ -20,31 +20,28 @@
 		// Note that some operating systems never admit this option.
 		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
 	}
-
-	if f == syscall.AF_UNIX ||
-		(f == syscall.AF_INET || f == syscall.AF_INET6) && t == syscall.SOCK_STREAM {
-		// Allow reuse of recently-used addresses.
-		err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
-		if err != nil {
-			return os.NewSyscallError("setsockopt", err)
-		}
-
-		// Allow reuse of recently-used ports.
-		// This option is supported only in descendants of 4.4BSD,
-		// to make an effective multicast application and an application
-		// that requires quick draw possible.
-		err = syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1)
-		if err != nil {
-			return os.NewSyscallError("setsockopt", err)
-		}
-	}
-
 	// Allow broadcast.
 	err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
 	if err != nil {
 		return os.NewSyscallError("setsockopt", err)
 	}
+	return nil
+}
 
+func setDefaultListenerSockopts(s int) error {
+	// Allow reuse of recently-used addresses.
+	err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	// Allow reuse of recently-used ports.
+	// This option is supported only in descendants of 4.4BSD,
+	// to make an effective multicast application and an application
+	// that requires quick draw possible.
+	err = syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
 	return nil
 }
 
diff --git a/src/pkg/net/sockopt_linux.go b/src/pkg/net/sockopt_linux.go
index 67c1dc8..7509c29 100644
--- a/src/pkg/net/sockopt_linux.go
+++ b/src/pkg/net/sockopt_linux.go
@@ -18,23 +18,20 @@
 		// Note that some operating systems never admit this option.
 		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
 	}
-
-	if f == syscall.AF_UNIX ||
-		(f == syscall.AF_INET || f == syscall.AF_INET6) && t == syscall.SOCK_STREAM {
-		// Allow reuse of recently-used addresses.
-		err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
-		if err != nil {
-			return os.NewSyscallError("setsockopt", err)
-		}
-
-	}
-
 	// Allow broadcast.
 	err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
 	if err != nil {
 		return os.NewSyscallError("setsockopt", err)
 	}
+	return nil
+}
 
+func setDefaultListenerSockopts(s int) error {
+	// Allow reuse of recently-used addresses.
+	err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
 	return nil
 }
 
diff --git a/src/pkg/net/sockopt_windows.go b/src/pkg/net/sockopt_windows.go
index 842bccc..46661e2 100644
--- a/src/pkg/net/sockopt_windows.go
+++ b/src/pkg/net/sockopt_windows.go
@@ -18,16 +18,18 @@
 		// Note that some operating systems never admit this option.
 		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
 	}
+	// Allow broadcast.
+	syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
+	return nil
+}
 
+func setDefaultListenerSockopts(s syscall.Handle, f, t int) error {
 	// Windows will reuse recently-used addresses by default.
 	// SO_REUSEADDR should not be used here, as it allows
 	// a socket to forcibly bind to a port in use by another socket.
 	// This could lead to a non-deterministic behavior, where
 	// connection requests over the port cannot be guaranteed
 	// to be handled by the correct socket.
-
-	// Allow broadcast.
-	syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
 	return nil
 }