1
0
mirror of https://github.com/golang/go synced 2024-11-25 02:27:56 -07:00

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
This commit is contained in:
Mikio Hara 2012-02-11 11:50:51 +09:00
parent 21a3aceb4a
commit 0e3514eaac
6 changed files with 44 additions and 33 deletions

View File

@ -38,6 +38,11 @@ func listenerSockaddr(s, f int, la syscall.Sockaddr, toAddr func(syscall.Sockadd
return la, nil return la, nil
} }
switch v := a.(type) { switch v := a.(type) {
case *TCPAddr, *UnixAddr:
err := setDefaultListenerSockopts(s)
if err != nil {
return nil, err
}
case *UDPAddr: case *UDPAddr:
if v.IP.IsMulticast() { if v.IP.IsMulticast() {
err := setDefaultMulticastSockopts(s) err := setDefaultMulticastSockopts(s)

View File

@ -32,6 +32,11 @@ func listenerSockaddr(s, f int, la syscall.Sockaddr, toAddr func(syscall.Sockadd
return la, nil return la, nil
} }
switch v := a.(type) { switch v := a.(type) {
case *TCPAddr, *UnixAddr:
err := setDefaultListenerSockopts(s)
if err != nil {
return nil, err
}
case *UDPAddr: case *UDPAddr:
if v.IP.IsMulticast() { if v.IP.IsMulticast() {
err := setDefaultMulticastSockopts(s) err := setDefaultMulticastSockopts(s)

View File

@ -19,6 +19,11 @@ func listenerSockaddr(s syscall.Handle, f int, la syscall.Sockaddr, toAddr func(
return la, nil return la, nil
} }
switch v := a.(type) { switch v := a.(type) {
case *TCPAddr, *UnixAddr:
err := setDefaultListenerSockopts(s)
if err != nil {
return nil, err
}
case *UDPAddr: case *UDPAddr:
if v.IP.IsMulticast() { if v.IP.IsMulticast() {
err := setDefaultMulticastSockopts(s) err := setDefaultMulticastSockopts(s)

View File

@ -20,31 +20,28 @@ func setDefaultSockopts(s, f, t int) error {
// Note that some operating systems never admit this option. // Note that some operating systems never admit this option.
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0) 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. // Allow broadcast.
err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1) err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
if err != nil { if err != nil {
return os.NewSyscallError("setsockopt", err) 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 return nil
} }

View File

@ -18,23 +18,20 @@ func setDefaultSockopts(s, f, t int) error {
// Note that some operating systems never admit this option. // Note that some operating systems never admit this option.
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0) 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. // Allow broadcast.
err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1) err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
if err != nil { if err != nil {
return os.NewSyscallError("setsockopt", err) 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 return nil
} }

View File

@ -18,16 +18,18 @@ func setDefaultSockopts(s syscall.Handle, f, t int) error {
// Note that some operating systems never admit this option. // Note that some operating systems never admit this option.
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0) 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. // Windows will reuse recently-used addresses by default.
// SO_REUSEADDR should not be used here, as it allows // SO_REUSEADDR should not be used here, as it allows
// a socket to forcibly bind to a port in use by another socket. // a socket to forcibly bind to a port in use by another socket.
// This could lead to a non-deterministic behavior, where // This could lead to a non-deterministic behavior, where
// connection requests over the port cannot be guaranteed // connection requests over the port cannot be guaranteed
// to be handled by the correct socket. // to be handled by the correct socket.
// Allow broadcast.
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
return nil return nil
} }